Перейти к основному содержимому

Генератор date

Когда брать. Нужна дата или дата-время — день рождения, дата документа, метка времени события — в заданном диапазоне и в нужном формате вывода.

Даты работают на собственном переносимом рантайме дат TDC: строгий парсер, UTC-календарь и локализованный форматтер, без зависимости от moment.js. Один и тот же конфиг рассчитан на одинаковые даты во всех реализациях.

Примеры вывода ниже иллюстративны — точные значения зависят от сида и могут отличаться между версиями ядра. Неизменны форма и формат.

Кратко

АтрибутЧто делает
valuebirth, today, now, одна дата или диапазон START..END
rangeДиапазон START..END — более новое написание той же идеи
from / toДве границы диапазона, заданные по отдельности
formatФормат вывода (см. раздел «Форматирование вывода» ниже); по умолчанию L
localen, es, ru или zh-cn; наследуется из <env>, если не задан
oldest / youngestВозрастное окно в годах для value="birth" (по умолчанию 80 и 10)
precisionday, second или millisecond

Диапазон описывает только что-то одно из value, range или пары from/to — это три написания одного и того же. Не задайте ни одного из них — и диапазон пойдёт от 1970-01-01 до текущего момента; см. Границ нет вовсе.

Случайная дата из диапазона

Задайте value в виде START..END (обе границы включены) — и получите случайную дату, равномерно распределённую внутри окна.

<gen type="date" value="2020-01-01..2025-12-31" format="YYYY-MM-DD"/>
./run demo.tdc (5 строк)
2024-08-15
2022-02-04
2020-06-21
2025-10-04
2021-03-31

Границы — часть окна. На узком окне в одну неделю это хорошо видно: на достаточном числе строк встречаются и 2024-06-01, и 2024-06-07:

<gen type="date" value="2024-06-01..2024-06-07" format="YYYY-MM-DD"/>
./run demo.tdc (6 строк)
2024-06-06
2024-06-03
2024-06-01
2024-06-07
2024-06-02
2024-06-02

Входные даты парсятся строго, в одной из форм:

  • дата: YYYY-MM-DD, YYYY.MM.DD или YYYY/MM/DD;
  • дата-время: YYYY-MM-DDTHH:mm, YYYY-MM-DDTHH:mm:ss или YYYY-MM-DDTHH:mm:ss.SSS;
  • диапазон: START..END.

Свободный текст (6 июня, 06/06/24) не принимается — используйте одну из строгих форм выше.

Атрибут range — то же окно, более новое написание

range="START..END" означает ровно то же, что value="START..END". Оно читается лучше, когда value иначе выглядело бы как ключевое слово, и это то самое написание, что и у шаблона date.range.

<gen type="date" range="2020-01-01..2024-12-31" format="YYYY-MM-DD"/>
./run demo.tdc (5 строк)
2023-11-08
2021-09-30
2020-05-23
2024-10-19
2021-01-14

Атрибут format управляет только тем, как дата записана, — он никогда не меняет окно, а окно никогда не зависит от формата.

from и to — границы по отдельности

Когда яснее назвать две границы порознь, используйте from и to. Это самое естественное написание для дата-временны́х окон, где диапазон иначе оказался бы длинной единой строкой.

<gen type="date"
from="2026-05-02T09:00:00"
to="2026-05-02T09:00:05"
format="YYYY-MM-DDTHH:mm:ss"/>
./run demo.tdc (5 строк)
2026-05-02T09:00:04
2026-05-02T09:00:01
2026-05-02T09:00:03
2026-05-02T09:00:00
2026-05-02T09:00:02

Границ нет вовсе — диапазон закрывают часы

Генератор date, которому не дали ни одной границы, всё равно выдаёт дату. Окно идёт от 1970-01-01 до текущего момента, то есть генератор читает часы, хотя в конфиге ни одна дата не упомянута:

<gen type="date" format="YYYY-MM-DD"/>
./run demo.tdc — тот же сид, с разницей в год
--now 2026-04-23    --now 2027-04-23
1972-06-01          1972-06-17
1994-11-20          1995-04-30
1972-05-06          1972-05-21

Так воспроизводимость теряется проще всего. Задайте генератору две границы или зафиксируйте часы через --now.

Одна граница третьим вариантом не является. from без to — ошибка (TDC150), и range="2020-01-01.." тоже (TDC151). Диапазон — это либо обе границы, либо ни одной.

День рождения через value="birth"

value="birth" выдаёт дату рождения относительно текущей даты, ограниченную возрастным окном. youngest и oldest — это возраст в годах (по умолчанию 10 и 80), поэтому youngest="18" oldest="65" даёт взрослых трудоспособного возраста.

<gen type="date" value="birth" youngest="18" oldest="65" format="DD.MM.YYYY"/>
./run demo.tdc (5 строк)
05.07.1997
23.11.1985
14.02.2003
30.09.1971
18.06.1990

Зачем это вместо фиксированного диапазона: окно следует за «сейчас», поэтому тот же конфиг и через год продолжит выдавать правдоподобные возрасты без правки дат. Для дня рождения, привязанного к цельному синтетическому человеку, шаблон person.b_day принимает те же атрибуты oldest/youngest/format.

По этой же причине даты и уезжают. Окно едет вслед за часами, поэтому завтра тот же сид даст другую дату рождения: возраст держится, дата — нет. Там, где вывод должен стоять на месте — снапшот-тест, фикстура, баг-репорт, — зафиксируйте часы через --now.

today и now

value="today" — текущая дата; value="now" — текущая дата и время. Оба читают часы runtime, поэтому это естественные метки для полей «сформировано» или «по состоянию на».

<gen type="date" value="today" format="LL" local="ru"/>
<gen type="date" value="now" format="YYYY-MM-DDTHH:mm:ss.SSS"/>
./run demo.tdc
value="today" format="LL" local="ru"             23 апреля 2026 г.
value="now"   format="YYYY-MM-DDTHH:mm:ss.SSS"   2026-04-23T12:00:00.000

Чтение часов — в этом и смысл обоих, и именно поэтому они невоспроизводимы: сид никак не влияет на то, какое сегодня число. Зафиксируйте часы через --now — и today с now в каждом прогоне вернут названный вами момент.

precision — шаг для дата-временны́х диапазонов

precision задаёт наименьший шаг, которым движется диапазон: day, second или millisecond. Для пятисекундного окна с шагом в целые секунды:

<gen type="date"
from="2026-05-02T09:00:00"
to="2026-05-02T09:00:05"
precision="second"
format="YYYY-MM-DDTHH:mm:ss"/>
./run demo.tdc (5 строк)
2026-05-02T09:00:04
2026-05-02T09:00:01
2026-05-02T09:00:03
2026-05-02T09:00:00
2026-05-02T09:00:02

Если precision опущен, значение по умолчанию следует типу диапазона:

Тип диапазонаШаг по умолчаниюЧто меняет precision
только дата (YYYY-MM-DD)один деньнужен редко — тут и так целые дни
дата-времяодна миллисекундаprecision="second" обнуляет миллисекунды

Используйте precision="second", когда нужны чистые, «человеческие» метки времени вместо миллисекундного шума; используйте precision="millisecond" (значение по умолчанию для дата-времени), когда нужна субсекундная точность.

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

format — это шаблон из маркеров. Он меняет только то, как дата записана, — само значение не трогается. По умолчанию — L (локаль-зависимая короткая дата).

Все маркеры на одном зафиксированном моменте — вторник 5 марта 2024, 09:04:07. День и месяц взяты однозначными нарочно, чтобы пары «с нулём / без нуля» отличались на глаз:

МаркерЗначениеПример
YYYYгод из 4 цифр2024
YYгод из 2 цифр24
MMMMполное имя месяцаMarch
MMMкороткое имя месяцаMar
MMмесяц из 2 цифр03
Mмесяц без ведущего нуля3
DDдень из 2 цифр05
Dдень без ведущего нуля5
ddddполное имя дня неделиTuesday
dddкороткое имя дня неделиTue
HHчас из 2 цифр (24ч)09
Hчас без ведущего нуля9
mmминута из 2 цифр04
mминута без ведущего нуля4
ssсекунда из 2 цифр07
sсекунда без ведущего нуля7
SSSмиллисекунды000
Zсмещение UTC с двоеточием+00:00
ZZсмещение UTC без двоеточия+0000
ISOдата в формате ISO 86012024-03-05
Lлокаль-зависимая короткая дата03/05/2024
LLлокаль-зависимая длинная датаMarch 5, 2024
LLLдлинная дата со временемMarch 5, 2024 09:04
LLLLона же с днём неделиTuesday, March 5, 2024 09:04

Имена месяцев и дней недели, а также четыре формы L, следуют локали — см. ниже. Всё остальное одинаково на любом языке.

Одна и та же дата в четырёх форматах — сид один, поэтому дата в каждой строке одинакова, различается только запись:

<gen type="date" value="2020-01-01..2024-12-31" format="YYYY-MM-DD"/>
<gen type="date" value="2020-01-01..2024-12-31" format="DD.MM.YYYY"/>
<gen type="date" value="2020-01-01..2024-12-31" format="DD MMM YYYY"/>
<gen type="date" value="2020-01-01..2024-12-31" format="LL"/>
./run demo.tdc
YYYY-MM-DD    DD.MM.YYYY    DD MMM YYYY    LL
2023-11-08    08.11.2023    08 Nov 2023    November 8, 2023
2021-09-30    30.09.2021    30 Sep 2021    September 30, 2021
2020-05-23    23.05.2020    23 May 2020    May 23, 2020

Литеральный текст в скобках

Всё, что в квадратных скобках, копируется в вывод дословно, поэтому дату можно обернуть в фиксированный текст:

<gen type="date" value="2024-03-15..2024-03-15" format="[дата:] YYYY-MM-DD"/>
./run demo.tdc
дата: 2024-03-15

Локаль-зависимые форматы: L и LL

L, LL, LLL и LLLL следуют локали, взятой из атрибута local (или local на <env>), — как и маркеры имён MMMM, MMM, dddd и ddd. Локаль по умолчанию — en. Числовые шаблоны вроде YYYY-MM-DD и DD.MM.YYYY никогда не зависят от локали — только от написанного вами шаблона.

Вот фиксированная дата 2024-03-15 под format="LL", сначала в локали по умолчанию (en), затем та же дата, перерисованная с local="ru", чтобы показать локализованное имя месяца и длинную форму, — намеренная демонстрация локализации:

<gen type="date" value="2024-03-15..2024-03-15" format="LL"/> <!-- по умолчанию en -->
<gen type="date" value="2024-03-15..2024-03-15" format="LL" local="ru"/> <!-- русская -->
./run demo.tdc
по умолчанию (en)   March 15, 2024
local="ru"          15 марта 2024 г.

L смещается так же: 03/15/2024 в en, 15.03.2024 в ru.

Подводные камни, всё в одном месте

  • Входные даты парсятся строго — используйте YYYY-MM-DD (или . / /), а не свободный текст.
  • Обе границы диапазона включены.
  • value, range и from/to — три написания одного окна, берите то, что читается лучше.
  • L / LL меняются с local; YYYY-MM-DD и подобные — нет.
  • Диапазоны только из дат шагают по дням; дата-временны́е — по миллисекундам, если не задан precision.
  • today, now, value="birth" и генератор без границ читают часы, поэтому одним сидом их не воспроизвести — фиксируйте часы через --now.
  • format применяется только к датам. На шаблонных идентификаторах (ИНН, СНИЛС, телефон…) это ошибка — оформляйте их фильтрами интерполяции.

См. также

  • format, range и local в справочнике атрибутов.
  • Шаблоныperson.b_day и date.range используют то же форматирование дат.