Экстраполя Cotonti: тип данных datetime — Дата и время

Как работают экстраполя типа datetime в Cotonti: хранение в Unix timestamp, параметры min/max/format, импорт, вывод с учётом часовых поясов и использование в шаблонах. Подробный разбор с примерами кода.

Экстраполя Cotonti: тип данных datetime — Дата и время 

Общие сведения 

Тип datetime в системе дополнительных полей (extrafields) Cotonti предназначен для хранения даты и времени в виде целого числа — Unix timestamp. Это значение представляет собой количество секунд, прошедших с полуночи 1 января 1970 года по UTC. Такой подход обеспечивает компактное хранение, простоту сравнения и корректное преобразование между часовыми поясами. 

Вся логика обработки полей типа datetime сосредоточена в трёх основных файлах: 

  • system/extrafields.php — функции для построения формы, импорта и вывода данных. 
  • system/forms.php — генерация выпадающих списков даты (cot_selectbox_date). 
  • system/functions.php — вспомогательные функции для работы с датами и временем (cot_import_date, cot_date, cot_mktime, cot_date2stamp, cot_stamp2date). 

Ниже мы детально рассмотрим каждый аспект работы с этим типом. 

Хранение значения в базе данных 

При создании экстраполя типа datetime через функцию cot_extrafield_add() в таблицу базы данных добавляется колонка со следующим SQL-типом: 

int DEFAULT '0'

Это означает:

  • Значение хранится как целое число (Unix timestamp).
  • Пустое значение (дата не выбрана) соответствует числу 0.
  • Максимальное значение определяется типом int (обычно 2^31-1), что позволяет хранить даты до 2038 года на 32-битных системах, но в большинстве современных окружений используется 64-битный PHP, где диапазон шире.

Фактически, в базе данных всегда находится либо 0, либо положительное число — количество секунд с начала эпохи.

Параметры поля (field_params)

Поле field_params в таблице cot_extra_fields для типа datetime хранит строку, состоящую из трёх компонентов, разделённых запятыми:

min,max,format
  • min — минимальный год (целое число). Используется для ограничения диапазона лет в форме редактирования и при импорте.
  • max — максимальный год (целое число).
  • format — строка формата даты/времени для вывода значения. Может быть как стандартным PHP-форматом (например, 'Y-m-d H:i'), так и ключом локализованного формата Cotonti (например, 'datetime_medium').

Поведение по умолчанию

Если параметры не заданы или заданы частично, действуют следующие правила:

  • Если min пуст или ≤ 0, используется 2000.
  • Если max пуст или ≤ 0, используется 2030.
  • Если format пуст, при выводе возвращается исходный Unix timestamp без форматирования.

Разбор параметров в коде

В функции cot_build_extrafields() (для построения формы) параметры разбираются так:

$extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']);
list($min, $max, $format) = explode(",", $extrafield['field_params'], 3);
$max = (int)$max > 0 ? $max : 2030;
$min = (int)$min > 0 ? $min : 2000;

В функции импорта cot_import_extrafields() разбираются только первые два параметра:

list($min, $max) = explode(",", $extrafield['field_params'], 2);

В функции вывода cot_build_extrafields_data():

list($min, $max, $format) = explode(",", $extrafield['field_params'], 3);
return (empty($format)) ? $value : cot_date($format, $value);

Таким образом, третий параметр (format) используется исключительно для вывода данных. При импорте и построении формы он игнорируется.

Формирование формы редактирования

Форма для ввода даты и времени генерируется функцией cot_build_extrafields() в ветке case 'datetime'.

Алгоритм cot_build_extrafields для datetime

  1. Инициализация глобальных переменных: global $sys;
  2. Очистка параметров: заменяются лишние пробелы вокруг запятых.
  3. Разбор параметров: извлекаются $min, $max, $format.
  4. Установка значений по умолчанию: если $max ≤ 0, берётся 2030; если $min ≤ 0, берётся 2000.
  5. Обработка относительных дат: если значение $data начинается с + или -, оно интерпретируется как смещение в секундах от текущего времени $sys['now']:

    $data = (mb_substr($data, 0, 1) == "+") ? $sys['now'] + (int)(mb_substr($data, 1)) : $data;
    $data = (mb_substr($data, 0, 1) == "-") ? $sys['now'] - (int)(mb_substr($data, 1)) : $data;

    Это позволяет использовать такие значения, как +86400 (завтра) или -3600 (час назад).

  6. Вызов генератора даты: cot_selectbox_date((int)$data, 'long', $name, (int)$max, (int)$min, true, $extrafield['field_html']).

Функция cot_selectbox_date()

Подробно рассмотрим её поведение на основе кода system/forms.php.

Параметры

  • $utime — Unix timestamp выбранной даты.
  • $mode — режим отображения. Для экстраполей всегда передаётся 'long' (полный набор: год, месяц, день, час, минута).
  • $name — базовое имя поля (например, rxtra_x200_last_promotion).
  • $max_year, $min_year — границы лет.
  • $usertimezone — флаг учёта часового пояса пользователя. Для экстраполей передаётся true.
  • $custom_rc — пользовательский ресурсный шаблон.

Шаги выполнения

  1. Проверка наличия кастомной функции: если определена cot_selectbox_date_custom(), она будет вызвана и результат возвращён без дальнейших действий.
  2. Хук form.date: разработчики могут переопределить вывод через плагины, подключённые к этому хуку.
  3. Определение имени ресурса: если имя поля содержит квадратные скобки (например, rxtra_date[user_id]), извлекается базовое имя до скобок для поиска ресурсных строк.
  4. Корректировка времени по часовому поясу:

    $utime = ($usertimezone && $utime > 0) ? ($utime + $usr['timezone'] * 3600) : $utime;

    Если $utime больше нуля и учёт часового пояса включён, к нему добавляется смещение текущего пользователя (в часах, умноженное на 3600). Это обеспечивает отображение времени в локальной зоне пользователя.

  5. Определение компонентов даты:
    • Если $utime == 0 (пустая дата), то компоненты ($s_year, $s_month, $s_day, $s_hour, $s_minute) устанавливаются в null. Затем проверяется буферизованное значение через cot_import_buffered(). Это позволяет восстановить выбранные значения после неудачной отправки формы (например, при ошибке валидации). Если буфер содержит массив, его значения используются для заполнения полей.
    • Если $utime > 0, то компоненты извлекаются через date('Y-m-d-H-i', $utime) и разбиваются по -.
  6. Формирование массива месяцев: используется языковой массив $L для локализованных названий месяцев (от $L['January'] до $L['December']).
  7. Создание выпадающих списков:
    • Год: cot_selectbox($s_year, $name.'[year]', range($max_year, $min_year, -1)). Диапазон лет от максимума к минимуму.
    • Месяц: cot_selectbox($s_month, $name.'[month]', array_keys($months), array_values($months)).
    • День: cot_selectbox($s_day, $name.'[day]', range(1, 31)).
    • Час: cot_selectbox($s_hour, $name.'[hour]', range(0, 23)) с ведущими нулями через sprintf('%02d', $i).
    • Минута: cot_selectbox($s_minute, $name.'[minute]', range(0, 59)).
  8. Выбор ресурсного шаблона: сначала ищется $R["input_date_{$mode}"], затем $R["input_date_{$rc_name}"], затем $custom_rc, иначе 'input_date'.
  9. Сборка HTML: через cot_rc() с передачей сгенерированных списков.

В результате форма содержит пять последовательных <select> элементов, обычно обёрнутых в контейнер из ресурсного файла input_date.

Импорт и сохранение значения

Импорт данных из формы выполняется функцией cot_import_extrafields() в ветке case 'datetime'.

Шаги импорта

  1. Очистка параметров: заменяются пробелы вокруг запятых.
  2. Разбор min и max (третий параметр не используется).
  3. Вызов cot_import_date($inputname, true, false, $source):
    • $inputname — имя поля (например, rxtra_x200_last_promotion).
    • true — учитывать часовой пояс пользователя.
    • false — не возвращать массив, а сразу timestamp.
    • $source — источник ('P' для POST).
  4. Обработка результата cot_import_date():
    • Если функция вернула null (поле пустое), устанавливается $import = 0.
    • Если заданы min или max (больше 0), выполняется корректировка года:

      list($s_year, $s_month, $s_day, $s_hour, $s_minute) = explode('-', @date('Y-m-d-H-i', $import));
      if ($min > $s_year) {
          $import = mktime($s_hour, $s_minute, 0, $s_month, $s_day, $min);
      }
      if ($max < $s_year) {
          $import = mktime($s_hour, $s_minute, 0, $s_month, $s_day, $max);
      }

      Таким образом, если выбранный год выходит за допустимые границы, он принудительно заменяется на min или max с сохранением остальных компонентов.

  5. Проверка обязательности: если поле обязательное (field_required = 1) и $import равно null, '' или 0, генерируется ошибка через cot_error().

Функция cot_import_date()

Эта функция находится в system/functions.php и играет ключевую роль.

Логика работы

  1. Проверка кастомной функции: если существует cot_import_date_custom(), она вызывается.
  2. Хук import.date: позволяет плагинам переопределить импорт.
  3. Получение данных:
    • Сначала пытается получить массив из источника через cot_import($name, $source, 'ARR'). Ожидается массив с ключами year, month, day, hour, minute.
    • Если массив пуст, предпринимается попытка прочитать значение как обычную строку (cot_import(..., 'TXT')). Это может быть дата в текстовом формате (например, 2025-12-31 23:59).
  4. Обработка строкового значения:
    • Если строка не пуста, вызывается cot_date2stamp($date), которая преобразует её в timestamp. Если преобразование не удалось, возвращается null.
  5. Обработка массива:
    • Компоненты массива проверяются на наличие, при отсутствии устанавливаются в 0.
    • Если все компоненты равны null (поле формы отправлено, но ни один элемент не выбран), возвращается null.
    • Если условие ($month && $day && $year) || ($day && $minute) истинно, создаётся timestamp через cot_mktime($hour, $minute, 0, $month, $day, $year).
    • В противном случае проверяется строка string и формат format, которые могут быть переданы в массиве. Если строка непуста, используется cot_date2stamp($string, $format). Иначе возвращается null.
  6. Корректировка часового пояса:

    if ($usertimezone) {
        $timestamp -= Cot::$usr['timezone'] * 3600;
    }

    Из полученного timestamp вычитается часовой пояс текущего пользователя, чтобы привести время к UTC перед сохранением в базу.

  7. Возврат результата:
    • Если $returnarray = true, возвращается массив с ключами stamp, year, month, day, hour, minute.
    • Иначе возвращается целочисленный timestamp.

Таким образом, итоговое значение, сохраняемое в базе данных, всегда является UTC timestamp.

Вывод значения в шаблонах

Для получения готового значения экстраполя используется функция cot_build_extrafields_data()system/extrafields.php).

Поведение для datetime

case 'datetime':
    $extrafield['field_params'] = str_replace([' , ', ', ', ' ,'], ',', $extrafield['field_params']);
    list($min, $max, $format) = explode(",", $extrafield['field_params'], 3);
    return (empty($format)) ? $value : cot_date($format, $value);
    break;
  • Из параметров извлекается только третий компонент — format.
  • Если format пуст, возвращается исходное значение $value (timestamp).
  • Если format задан, вызывается функция cot_date($format, $value).

Функция cot_date()

Расположена в system/functions.php. Используется для локализованного форматирования даты.

function cot_date($format, $timestamp = null, $usertimezone = true)
{
    global $lang, $Ldt;
    if (is_null($timestamp)) {
        $timestamp = Cot::$sys['now'];
    }
    $timestamp = (int) $timestamp;
    if ($usertimezone) {
        $timestamp += Cot::$usr['timezone'] * 3600;
    }
    $datetime = (isset($Ldt[$format])) ? @date($Ldt[$format], $timestamp) : @date($format, $timestamp);
    // ... замена английских названий месяцев/дней на локализованные
    return ($lang == 'en') ? $datetime : str_replace($search, $replace, $datetime);
}
  • Если $timestamp не передан, берётся текущее время Cot::$sys['now'].
  • При $usertimezone = true к timestamp добавляется часовой пояс пользователя (Cot::$usr['timezone'] * 3600), то есть время из UTC переводится в локальное для отображения.
  • Если формат присутствует в массиве $Ldt (локализованные форматы), используется он, иначе — переданный PHP-формат.
  • После форматирования выполняется замена английских названий дней недели и месяцев на локализованные версии из $L (если язык не английский).

Взаимодействие с часовыми поясами

Ключевая особенность типа datetimeкорректная работа с часовыми поясами пользователей. Схема следующая:

  1. При вводе (импорте):
    • Пользователь выбирает дату и время в своей локальной зоне.
    • Функция cot_import_date() вычитает его часовой пояс (Cot::$usr['timezone'] * 3600), приводя время к UTC.
    • В базу сохраняется UTC timestamp.
  2. При выводе:
    • Из базы извлекается UTC timestamp.
    • Функция cot_date() добавляет часовой пояс текущего пользователя, переводя время обратно в локальное.
    • Затем происходит форматирование и локализация.

Таким образом, каждый пользователь видит дату и время в своей собственной зоне, независимо от того, где была сохранена запись.

Часовой пояс пользователя хранится в Cot::$usr['timezone'] как смещение в часах от UTC (например, 3 для Москвы).

Использование в плагинах и модулях

Регистрация поля

Для создания экстраполя типа datetime в плагине используется функция cot_extrafield_add(). Пример:

cot_extrafield_add(
    'users',                    // таблица, к которой добавляется поле
    'my_event_datetime',        // имя поля (без префикса таблицы)
    'datetime',                 // тип
    '',                         // html-конструкция (пусто — стандартная)
    '',                         // варианты (не используются для datetime)
    '',                         // значение по умолчанию (timestamp или 0)
    false,                      // обязательность
    'HTML',                     // парсер (не влияет на datetime)
    'Дата события',             // описание
    '2000,2030,datetime_medium' // параметры: min,max,format
);

После вызова в таблице cot_users появится колонка user_my_event_datetime с типом int DEFAULT '0'.

Сохранение значения

В плагине при обработке POST-запроса:

$exfld = [/* массив описания поля, полученный через cot_load_extrafields() */];
$oldValue = $existingData['user_my_event_datetime'] ?? 0;
$newValue = cot_import_extrafields('rxtra_my_event_datetime', $exfld, 'P', $oldValue, 'xtra_');
// $newValue — UTC timestamp или 0

Если поле обязательное, функция автоматически сгенерирует ошибку при пустом значении.

После успешного импорта всех полей обычно вызывается cot_extrafield_movefiles() (для файловых полей, но не влияет на datetime).

Получение значения

Для получения значения из базы данных достаточно обычного SQL-запроса или использования API плагина. Значение будет целым числом (timestamp).

Использование в шаблонах

Автоматическая генерация тегов

Для пользователей Cotonti предоставляет функцию cot_generate_usertags(), которая создаёт теги для всех экстраполей, включая datetime.

Например, для поля user_x200_last_promotion будут созданы следующие теги:

  • {USERS_DETAILS_XTRA_X200_LAST_PROMOTION} — отформатированное значение (если format задан) или timestamp.
  • {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_TITLE} — название поля.
  • {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_VALUE} — сырое значение (timestamp).

Обратите внимание, что в стандартной генерации тегов для экстраполей пользователей используется префикс user_, но он не включается в имя тега. В плагинах, подобных xtradbrowusers, могут быть свои соглашения.

Проверка наличия значения

Поскольку пустая дата хранится как 0, для проверки заполненности поля следует использовать тег _VALUE:

<!-- IF {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_VALUE} -->
    <div class="contact-label">{USERS_DETAILS_XTRA_X200_LAST_PROMOTION_TITLE}</div>
    <div class="contact-value">{USERS_DETAILS_XTRA_X200_LAST_PROMOTION}</div>
<!-- ENDIF -->

Условие <!-- IF {TAG_VALUE} --> истинно, если значение не пустое и не равно строке "0". Такой подход гарантирует, что блок с датой не появится, если дата не выбрана.

Альтернативная проверка с явным сравнением

<!-- IF {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_VALUE} > 0 -->
    ... вывод ...
<!-- ENDIF -->

Оба способа эквивалентны для datetime, так как пустое значение всегда 0. Явное сравнение может быть полезно, если требуется сравнить с текущей датой или другими значениями.

Вывод даты в заданном формате

Если формат не задан в параметрах поля, можно отформатировать timestamp прямо в шаблоне, используя PHP-функцию date внутри {PHP}:

{PHP.date('d.m.Y H:i', {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_VALUE})}

Но обычно формат указывается в field_params, и тогда обычный тег уже возвращает готовую строку.

Пример полного блока

<!-- IF {USERS_DETAILS_XTRA_X200_LAST_PROMOTION_VALUE} -->
<div class="d-flex align-items-center mb-3">
    <div class="contact-icon calendar me-3">
        <i class="fa-solid fa-calendar-alt fa-xl"></i>
    </div>
    <div>
        <div class="contact-label">{USERS_DETAILS_XTRA_X200_LAST_PROMOTION_TITLE}</div>
        <div class="contact-value">{USERS_DETAILS_XTRA_X200_LAST_PROMOTION}</div>
    </div>
</div>
<!-- ENDIF -->

Особенности и подводные камни

Нулевое значение (0)

  • Пустая дата всегда хранится как 0.
  • При выводе с заданным форматом cot_date() вернёт дату 1 января 1970 года, что может выглядеть как «01.01.1970». Поэтому всегда проверяйте наличие значения через _VALUE перед выводом.
  • При проверке обязательности в импорте 0 считается пустым значением.

Относительные даты

Если в значение поля в БД каким-либо образом попало число с ведущим + или - (например, +86400), то при построении формы оно будет преобразовано в $sys['now'] + 86400. Это удобно для динамических сроков, но требует осторожности: при сохранении такого значения через форму оно будет зафиксировано как конкретная дата.

Корректировка года по min/max

  • min и max влияют на список годов в форме, а также на импорт: если выбранный год меньше min, он заменяется на min, если больше max — на max.
  • Эти параметры не накладывают ограничений на значение, уже сохранённое в БД, если оно было изменено вручную.

Часовой пояс

  • При импорте время корректируется по часовому поясу текущего пользователя (того, кто заполняет форму).
  • При выводе используется часовой пояс пользователя, просматривающего страницу.
  • Если пользователь не авторизован, Cot::$usr['timezone'] может быть 0 или значение по умолчанию, обычно UTC.

Парсинг строк

cot_import_date() поддерживает импорт не только из массива компонентов, но и из обычной строки с датой. Это может быть полезно при интеграции с внешними источниками данных. Однако строковый ввод не используется в стандартной форме.

Хуки

  • Хук form.date позволяет полностью заменить вывод формы даты.
  • Хук import.date позволяет заменить логику импорта.
  • Если определена функция cot_selectbox_date_custom(), она имеет приоритет.

Влияние обязательности

Если поле datetime помечено как обязательное, пустое значение (0) вызовет ошибку валидации. Ошибка будет связана с именем поля, что позволяет показать сообщение рядом с соответствующей частью формы.

Заключение

Тип datetime в Cotonti является мощным инструментом для хранения дат и времени с учётом часовых поясов. Он хранит данные в виде UTC timestamp, обеспечивает удобный ввод через набор выпадающих списков и гибкий вывод с локализацией. При использовании в шаблонах важно помнить о проверке значения через _VALUE, чтобы корректно скрывать блоки с пустой датой.

Разработчики плагинов могут полностью контролировать поведение поля через параметры min, max и format, а также использовать хуки для расширения функциональности. Знание деталей работы функций cot_build_extrafields, cot_import_extrafields, cot_selectbox_date и cot_date позволяет эффективно интегрировать этот тип в любые модули и темы оформления.

Статья основана исключительно на анализе исходного кода Cotonti, и не содержит предположений или недостоверной информации.

Вернуться к началу

11 минут чтения Sodium Carbonate

Комментарии (0)

Комментарии отсутствуют
Добавление комментариев доступно только зарегистрированным пользователям

Обсуждение страницы в Telegram

Рекомендуемые товары и услуги

Extrafields Users Custom

Extrafields Users Custom

плагин для Cotonti CMF, позволяющий добавлять неограниченное число дополнительных полей к профилям
Плагин “Custom Extrafields” для Cotonti

Плагин “Custom Extrafields” для Cotonti

плагин меняет стратегию хранения: для всех зарегистрированных через него экстраполей создаётся
Extrafields Market Custom

Extrafields Market Custom

Назначение этого плагина для Cotonti: добавляет экстраполя для модуля «Market PRO v.5» в собственную

Автор контента

webitproff

Онлайн

Sodium Carbonate

Последняя авторизация: 16.08.2026 16:01

  • Страница размещена: 16.08.2026 13:02
  • Последнее обновление: 16.08.2026 14:00
  • Язык:

Связанные статьи

Похожие страницы

Блог это несложный по функционалу нишевый тип контентного сайта
1 Блог как понятие обозначает категорию веб-сайтов, представляющую из себя онлайновый дневник или сборник хронологически
Тип custom в переменных конфигурации
2 Тип 'custom' в переменных конфигурации Возможности типа 'custom' Новый тип custom предоставляет
Экстраполя в шаблонах в модуле "Page" Cotonti
3 В коде Cotonti в модуле "Page" для добавления страницы есть участок, который обрабатывает дополнительные поля
Локализация (перевод) названия и значений экстраполя
4 подробная пошаговая инструкция для новичков: как создать экстраполе типа select (выпадающий список) с названием «статус
Настройка переменных конфигурации расширений Cotonti и типы данных
5 Настройка переменных конфигурацииМеханизм Cotonti спроектирован таким образом, что позволяет при создании Расширения
Cotonti Siena CMF • 30.11.2025 14:05 Administrator

Рекомендуемые темы форума для этой статьи

Руководство по тегам в шаблонах - полная версия шпаргалка

Руководство по тегам в шаблонах - полная версия шпаргалка

Плагин 'xtradbrowusers'. Интеграция и прописание тегов для вывода экстраполей в шаблонах. Текст
#215 | Постов: 7 | Просмотров: 88
Плагин “Custom Extrafields” - Памятка про установку демо экстраполей

Плагин “Custom Extrafields” - Памятка про установку демо экстраполей

Статья-памятка: установочный файл демо-полей php-обработчик xtradbrowpage.install.php
#206 | Постов: 1 | Просмотров: 2244
Экстраполя в Cotonti: полное руководство по типу «Список с множественным выбором» (checklistbox)

Экстраполя в Cotonti: полное руководство по типу «Список с множественным выбором» (checklistbox)

Данное руководство является продолжением серии статей о дополнительных полях (Extrafields) в Cotonti
#204 | Постов: 1 | Просмотров: 2250