JavaScript / 38 минут
Даты и регулярные выражения
Работайте с датами, часовыми поясами и проверяйте строки регулярными выражениями.
- Работайте с датами, часовыми поясами и проверяйте строки регулярными выражениями.
- Применить тему в задаче «Даты и регулярные выражения» и объяснить граничные случаи.
Около 8 минут на чтение и разбор примеров. Практика — отдельно, в своём темпе.
Момент времени и календарная запись
Дата может означать конкретный момент времени или календарный день без времени. Это разные модели. Запись дня рождения не всегда должна превращаться в полночь UTC, а момент отправки сообщения должен иметь согласованную временную основу. Ошибка выбора модели часто проявляется как сдвиг на день у пользователя другого часового пояса.
Date представляет момент через число миллисекунд относительно Unix-эпохи. Локальные методы интерпретируют его в часовом поясе среды, UTC-методы — в UTC. Для отображения удобно использовать Intl.DateTimeFormat с нужными locale и timeZone. Не полагайтесь на случайный формат строки, который вы увидели на своей машине: у другого пользователя окружение может отличаться.
const instant = new Date('2026-10-24T00:00:00Z');
console.log(instant.toISOString()); // 2026-10-24T00:00:00.000Z
console.log(new Intl.DateTimeFormat('ru-RU', {
timeZone: 'Asia/Vladivostok', dateStyle: 'medium',
}).format(instant));Проверка даты и календарные ограничения
Созданный Date может быть некорректным. Это проверяют через его timestamp, например Number.isNaN(value.getTime()). Само существование объекта Date не гарантирует корректного момента. Также важно, что некоторые числовые способы создания даты нормализуют выходящие за диапазон компоненты: они не обязаны отвергнуть несуществующий календарный день в том виде, в каком вы ожидаете.
Если контракт принимает YYYY-MM-DD как дату без времени, отдельно проверяют форму, диапазоны месяца и реальность дня. Не превращайте ввод с неуказанным часовым поясом в момент произвольным локальным парсингом. В API лучше документировать формат явно и сохранять различие между календарным значением и timestamp.
Регулярное выражение как шаблон текста
RegExp описывает шаблон поиска или проверки строк. Литерал /pattern/ удобен для постоянного шаблона, конструктор RegExp — для динамического. При динамической сборке специальные символы входных данных требуют отдельного экранирования; иначе пользовательский текст станет частью языка шаблона. В простой проверке test возвращает boolean.
const identifier = /^[a-z][a-z0-9_]*$/i;
console.log(identifier.test('course_12')); // true
console.log(identifier.test('12course')); // falseКвадратные скобки задают набор символов, диапазон ограничивает варианты, * разрешает ноль или больше повторений, + требует минимум одно. Не учите шаблоны как магические строки: разбирайте их слева направо и объясняйте роль каждого элемента. Для понятной проверки небольшого формата иногда обычный код читается лучше сложного выражения.
Якоря, группы и флаги
^ и $ связывают совпадение с границами ввода с учётом режима выражения. Без них шаблон даты может найти подходящий кусок внутри лишнего текста. Группы помогают выделить части, а match возвращает структуру найденного совпадения. Флаги меняют правила: i влияет на регистр, g — на глобальный поиск, u — на Unicode-семантику соответствующих конструкций.
const format = /^(\d{4})-(\d{2})-(\d{2})$/;
const match = '2026-10-24'.match(format);
if (match) {
const [, year, month, day] = match;
console.log(year, month, day); // строки
}Захваченные числа остаются строками до явного преобразования. Шаблон с g может иметь изменяющийся lastIndex при повторных test, поэтому его нельзя бездумно применять как независимый валидатор одного поля между вызовами. Выбор флагов должен соответствовать задаче, а не привычке добавлять все известные буквы.
Ограничения и безопасная сложность
Регулярное выражение не является универсальным парсером любого языка. Для JSON нужен JSON.parse, для HTML — DOM-парсер, для URL — подходящий URL API. Очень сложные шаблоны с неоднозначными вложенными повторениями могут приводить к дорогому перебору на специально подобранном вводе. Ограничение длины и понятный шаблон полезнее случайной «универсальной» проверки из неизвестного примера.
const text = 'JS, TS; Node';
const parts = text.split(/[,;]\s*/);
console.log(parts); // ['JS', 'TS', 'Node']Валидация электронной почты, адреса или международного имени требует предметных правил и часто специализированной библиотеки. Не отвергайте законные значения только потому, что самодельный шаблон считает буквой лишь a-z. Формат ввода и набор допустимых символов должны следовать требованиям продукта.
Практика: форма не равна смыслу
В задании проверяется только форма YYYY-MM-DD. Поэтому строка 2026-99-99 должна пройти эту конкретную проверку, хотя календарной датой не является. Это намеренное разделение обязанностей: один небольшой валидатор отвечает за структуру, следующий мог бы отвечать за календарь. «Исправление» ответа на false нарушило бы заданный контракт.
Проверьте слишком короткий месяц, лишний префикс, пустую строку и правильное количество цифр. После решения добавьте вторую отдельную функцию календарной проверки и тесты високосного года. Затем объясните, почему хранение даты занятия как локального календарного дня отличается от хранения времени отправки события в ISO-формате с Z.