Date Utils
Central Design System includes a set of functions for working with the native JS Date: mask-based formatting, string parsing, arithmetic, comparison and calendar math. You don't need a separate date library (dayjs, date-fns) for everyday tasks. The date and time components use the very same functions — CdsDateInput, CdsDatePicker, CdsTimePicker — so format masks are identical in the utilities and in the components.
The functions accept a Date, a timestamp (milliseconds) or a date string, return a native Date and never mutate the arguments you pass — the result is always a new object.
Setup
The utilities are exported from the package under the utils namespace:
import { utils } from '@central-design-system/components';
const { formatDate, addToDate } = utils;
formatDate(new Date(2026, 7, 18), 'DD.MM.YYYY'); // '18.08.2026'Formatting — formatDate
formatDate(value, mask, dateLocale?) turns a date into a string using a mask:
const { formatDate } = utils;
formatDate(new Date(2026, 7, 18, 14, 30), 'DD.MM.YYYY HH:mm'); // '18.08.2026 14:30'
formatDate(Date.now(), 'D MMM YYYY'); // '18 Авг 2026'
formatDate(new Date(2026, 7, 18), 'dddd'); // 'Вторник'Without a mask, an ISO-like format is used: YYYY-MM-DDTHH:mm:ss.SSSZ. For an invalid value the function returns undefined.
Month and weekday names come from the Russian date locale by default. To print them in another language, pass a date locale as the third argument — the built-in ones live in the locales export:
import { locales, utils } from '@central-design-system/components';
utils.formatDate(new Date(2026, 7, 18), 'dddd, D MMMM', locales.enDate);
// 'Tuesday, 18 August'Your own language is plugged in as a TDateLocale object — the same fields as locales.ruDate. See the Internationalization guide for more on date locales.
Format tokens
| Unit | Token | Result |
|---|---|---|
| Year | YY / YYYY | 26 / 2026 |
| Month | M / MM | 8 / 08 |
| Month (name) | MMM / MMMM | Авг / Август |
| Quarter | Q / Qo | 3 / 3rd |
| Day of month | D / Do / DD | 18 / 18th / 18 |
| Day of year | DDD / DDDD | 230 / 230 (zero-padded to 3 digits) |
| Day of week | d | 2 (0 — Sunday) |
| Day of week (name) | dd / ddd / dddd | Вт / Вт / Вторник |
| Day of week (ISO) | E | 2 (1 — Monday, 7 — Sunday) |
| Week of year | w / ww | 34 / 34 |
| Hour (0–23) | H / HH | 14 / 14 |
| Hour (1–12) | h / hh | 2 / 02 |
| Minute | m / mm | 30 / 30 |
| Second | s / ss | 5 / 05 |
| Fractions of a second | S / SS / SSS | 1 / 12 / 123 |
| Time zone | Z / ZZ | +03:00 / +0300 |
| Meridiem | A / a / aa | PM / pm / p.m. |
| Unix time | X / x | seconds / milliseconds |
Ordinal suffixes (Do, Qo) are English (1st, 2nd…) regardless of the locale.
Arbitrary text inside a mask is escaped with square brackets:
formatDate(new Date(2026, 7, 18), '[Сегодня] DD.MM'); // 'Сегодня 18.08'Parsing — extractDate and splitDate
extractDate(str, mask, dateLocale?) parses a string with a mask and returns a Date:
const { extractDate } = utils;
extractDate('21.03.1985', 'DD.MM.YYYY'); // Date: 21 March 1985
extractDate('2019-10-29 23:12', 'YYYY-MM-DD HH:mm'); // Date: 29 October 2019, 23:12Month and day names inside the string are recognized through the date locale — Russian by default, just like in formatDate.
A non-existent day overflows following the rules of the native Date: extractDate('30.02.2024', 'DD.MM.YYYY') gives 1 March 2024. When you need strict input validation, format the result back and compare it with the string:
const strict = (str: string, mask: string) => formatDate(extractDate(str, mask), mask) === str;
strict('18.08.2026', 'DD.MM.YYYY'); // true
strict('30.02.2024', 'DD.MM.YYYY'); // false — overflowed into 01.03.2024If you don't need a Date, splitDate(str, mask, dateLocale?) splits the string into its parts — an IRawDate object with the fields year, month, day, hour, minute, second, millisecond (anything not found is null):
const { splitDate } = utils;
splitDate('18.08.2026', 'DD.MM.YYYY');
// { year: 2026, month: 8, day: 18, hour: null, … }Creating and changing
buildDate
buildDate(modified, utc?) — the current moment with individual parts replaced. Handy when you need "now, but at 15:00" or "today, but in 2010":
const { buildDate } = utils;
buildDate({ year: 2010, day: 5, hour: 15 });
// current month, minutes and seconds; year 2010, day 5, hour 15Supported object fields: year, month (1–12), day (or date), hour, minute, second, millisecond.
adjustDate
adjustDate(date, modified, utc?) — the same thing, but for an arbitrary date:
const { adjustDate } = utils;
adjustDate(new Date(2026, 10, 2), { year: 2010, month: 2 });
// Date: 2 February 2010Note that month here is 1-based (February is 2), unlike in the Date constructor.
addToDate / subtractFromDate
Add and subtract intervals. The object fields are the same, but they mean "how much to add" rather than "what to set":
const { addToDate, subtractFromDate } = utils;
addToDate(new Date(2026, 2, 7), { day: 7, month: 1 }); // Date: 14 April 2026
subtractFromDate(new Date(2026, 2, 7), { hour: 24 }); // Date: 6 March 2026startOfDate / endOfDate
The start and the end of a period — year, month, day, hour, minute or second:
const { startOfDate, endOfDate } = utils;
startOfDate(new Date(2026, 7, 18, 14, 30), 'year'); // Date: 1 January 2026, 00:00:00.000
endOfDate(new Date(2026, 7, 18, 14, 30), 'month'); // Date: 31 August 2026, 23:59:59.999Period unit: 'year', 'month', 'day', 'hour', 'minute', 'second' (the plural form is accepted too).
Comparison and ranges
isSameDate
Compares dates down to a unit: 'year' — the year only, 'month' — month and year, 'day' — the calendar day, and so on. Without a unit, the timestamps are compared in full.
const { isSameDate } = utils;
isSameDate(new Date(2026, 7, 1), new Date(2026, 7, 30), 'month'); // true
isSameDate(new Date(2026, 7, 1), new Date(2026, 7, 30), 'day'); // falsegetDateDiff
The difference between two dates in the chosen unit (days by default):
const { getDateDiff } = utils;
getDateDiff(new Date(2026, 4, 12), new Date(2026, 3, 8)); // 34 (days)
getDateDiff(new Date(2026, 4, 12), new Date(2026, 3, 8), 'months'); // 1isBetweenDates / getDateBetween
isBetweenDates(date, from, to, opts?) checks whether a date falls inside a range. The bounds are excluded by default; the inclusiveFrom and inclusiveTo options include them, and onlyDate: true compares calendar days only, ignoring the time:
const { isBetweenDates } = utils;
isBetweenDates(date, from, to); // strict range
isBetweenDates(date, from, to, { inclusiveFrom: true, inclusiveTo: true, onlyDate: true });getDateBetween(date, min, max) clamps a date to a range: it returns the date itself if it is inside, otherwise the nearest bound:
const { getDateBetween } = utils;
getDateBetween(new Date(2025, 0, 1), new Date(2026, 0, 1), new Date(2026, 11, 31));
// Date: 1 January 2026 — the date is below the minimum, so the min bound came backgetMinDate / getMaxDate
The smallest and the largest of a set of dates. They return a timestamp (number) — wrap it in new Date() if you need a date object:
const { getMinDate, getMaxDate } = utils;
const min = getMinDate(new Date(2026, 6, 24), new Date(2026, 5, 20), new Date(2026, 6, 26));
new Date(min); // Date: 20 June 2026
const dates = [/* Date[] */];
const max = getMaxDate(dates[0], ...dates.slice(1));Calendar
const { getDayOfWeek, getWeekOfYear, getDayOfYear, daysInMonth } = utils;
getDayOfWeek(new Date(2026, 7, 16)); // 7 — Sunday (ISO: 1 — Monday)
getWeekOfYear(new Date(2026, 0, 4)); // 1 — ISO week number in the year
getDayOfYear(new Date(2026, 1, 4)); // 35 — ordinal day in the year
daysInMonth(new Date(2024, 1, 15)); // 29 — February of a leap yearOther
isValidDate
Checks whether a value parses into a date:
const { isValidDate } = utils;
isValidDate('2026-08-18'); // true
isValidDate('не дата'); // falseThe check is syntactic — it does not catch non-existent calendar days (see splitDate above).
cloneDate
A copy of a date. Useful before handing it to third-party code that might mutate the object (CDS utilities themselves never modify their arguments):
const { cloneDate } = utils;
const copy = cloneDate(original);inferDateFormat
Detects the shape of a value — handy for returning the result in the same form the value came in:
const { inferDateFormat } = utils;
inferDateFormat(new Date()); // 'date'
inferDateFormat(1787059805000); // 'number'
inferDateFormat('18.08.2026'); // 'string'