1.8Kпросмотров
25.3%от подписчиков
17 февраля 2026 г.
Score: 1.9K
📅 LocalDate и DateTimeFormatter: вечная путаница с YYYY и yyyy Каждый Новый год эта ошибка просыпается и незаметно портит данные в логах, отчётах и экспортах. Разница между YYYY и yyyy - всего одна буква, но она может сдвинуть дату на целый год вперёд или назад в первую неделю января. Вот как не попасть в эту ловушку и почему это происходит 👇 📁 Шаг 1: Наглядный пример ошибки (31 декабря 2024 года)
DateTimeFormatter wrongFormatter = DateTimeFormatter.ofPattern("dd.MM.YYYY");
DateTimeFormatter correctFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); LocalDate date = LocalDate.of(2024, 12, 31); System.out.println("Неправильно (YYYY): " + date.format(wrongFormatter)); // 31.12.2025 ← вот он, сдвиг на год!
System.out.println("Правильно (yyyy): " + date.format(correctFormatter)); // 31.12.2024
➡️ Да, 31 декабря 2024 года форматируется как... 2025 год. Это не баг, а фича, о которой мало кто знает. 📁 Шаг 2: В чём разница? (Год vs Год недели)
- yyyy — это обычный календарный год (year-of-era). То, что мы все понимаем под годом.
- YYYY — это год недели (week-based-year) по стандарту ISO 8601. ➡️ YYYY используется вместе с номером недели (ww) и днём недели (E). Он нужен для отображения года, к которому относится неделя, а не календарная дата. 📁 Шаг 3: Почему происходит сдвиг? (Магия первой недели года)
По ISO 8601:
1. Неделя начинается с понедельника.
2. Первая неделя года — это неделя, содержащая первый четверг года.
3. Год недели (YYYY) — это год, к которому относится эта неделя. // Пример: 1 января 2025 года — это среда
LocalDate jan1 = LocalDate.of(2025, 1, 1); System.out.println("Год недели: " + jan1.format(DateTimeFormatter.ofPattern("YYYY")));
// 2025 — потому что неделя (30 дек - 5 янв) содержит первый четверг 2025 года (2 января) // А 30 декабря 2024 года — это понедельник, начало недели 1 (2025 года!)
LocalDate dec30 = LocalDate.of(2024, 12, 30);
System.out.println("Год недели: " + dec30.format(DateTimeFormatter.ofPattern("YYYY")));
// 2025 — потому что эта неделя (30 дек - 5 янв) содержит первый четверг 2025 года
➡️ Критические периоды: последние 3-4 дня декабря и первые 3-4 дня января. Именно здесь YYYY и yyyy чаще всего расходятся. 📁 Шаг 4: Где используется YYYY (правильно)
Только вместе с номером недели!
// Для отображения номера недели и года недели (отчёты, планирование)
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("'Неделя' ww, YYYY");
LocalDate date = LocalDate.of(2024, 12, 30); System.out.println(date.format(weekFormatter));
// "Неделя 01, 2025" ← это правильно для систем, работающих по неделям
➡️ Используй YYYY только если ты точно понимаешь, что такое год недели, и используешь его с ww (номер недели). 📁 Шаг 5: Где НЕЛЬЗЯ использовать YYYY (опасные случаи)
1. Логирование — дата в логах внезапно станет 2025 годом 30 декабря.
2. Экспорт в CSV/Excel для отчётности.
3. Формирование имён файлов с датами.
4. Любые даты, которые потом будут парситься обратно. // ❌ Опасный парсинг (может сломаться)
String wrong = "31.12.2024";
LocalDate parsed = LocalDate.parse(wrong, DateTimeFormatter.ofPattern("dd.MM.YYYY"));
// Может выкинуть исключение или спарсить не ту дату 📁 Шаг 6: Как избежать ошибки навсегда 1. Используй готовые форматеры вместо ручных паттернов: DateTimeFormatter.ISO_LOCAL_DATE; // yyyy-MM-dd DateTimeFormatter.BASIC_ISO_DATE; // yyyyMMdd 2. Пиши тесты на граничные даты: @Test void dateFormatting_aroundNewYear() { LocalDate dec30 = LocalDate.of(2024, 12, 30); LocalDate jan1 = LocalDate.of(2025, 1, 1); assertThat(dec30.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))) .isEqualTo("30/12/2024"); assertThat(jan1.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))) .isEqualTo("01/01/2025"); } 3. Включи в code review проверку всех DateTimeFormatter на наличие YYYY. 🗣️ Запомни: YYYY - это не опечатка, а отдельная концепция. Используй yyyy для всего, что связано с календарными датами.