Помилки timezone переживають звичайні тести, бо більшість днів поводиться очікувано. Потім перехід на літній або зимовий час створює локальну годину, якої не існує, повторює іншу годину або змінює різницю між двома офісами. Головна помилка — сприймати timezone як постійний числовий offset. Offset описує один момент, а timezone містить правила перетворення instant у локальний календар.

Offset і timezone відповідають на різні питання

UTC+02:00 показує відстань локального годинника від UTC у конкретний момент. Europe/Kyiv визначає регіон, offset якого може змінюватися за історичними та майбутніми правилами. Якщо подія завжди має відбуватися о 9:00 локального часу, збереження лише поточного offset втратить потрібне правило.

IANA timezone identifier дозволяє бібліотеці застосувати актуальну регіональну базу. Її потрібно оновлювати, бо уряди іноді змінюють календарні правила з невеликим попередженням.

Деякі локальні моменти не існують

Коли годинник переводять уперед, частина локального часу пропускається. Розклад на цей проміжок потребує policy: відхилити час, перенести вперед або попросити користувача вибрати. Бібліотеки мають різні defaults, тому мовчазне adjustment може здивувати.

Під час переведення назад певна година трапляється двічі. Локальне 1:30 може означати два різні instant. Для точного вибору потрібен offset, fold indicator або явне disambiguation rule.

Recurring event повинен зберігати локальний намір

Щотижнева зустріч о 10:00 належить календарю учасників, а не одному постійному UTC timestamp. Додавання рівно семи разів по 24 години може пересунути зустріч після daylight-saving transition. Кожен occurrence потрібно обчислювати в intended timezone, а потім перетворювати на instant.

Job, який запускається кожні 24 elapsed hours, є duration-based і може навмисно зміщуватися відносно локального годинника. Вимога повинна чітко розрізняти календарний та duration-based розклад.

Timezone користувача не завжди керує подією

Мандрівник переглядає рейс у timezone аеропорту вильоту. Звіт компанії закривається за часом головного офісу. Віддалений працівник може хотіти reminder у поточній локальній зоні. Застосунок повинен визначити, чий годинник керує подією, а не автоматично використовувати browser timezone.

Інтерфейс може показати кілька зон для контексту, але stored model має зберегти authoritative timezone та instant. Конвертація на display edge підтримує послідовність даних.

Date-only не є midnight instant

День народження, дата рахунку або свято можуть бути календарною датою без часу й timezone. Перетворення на midnight UTC покаже попередній день для частини користувачів. Такі поняття потрібно зберігати як date й порівнювати календарною логікою.

Те саме стосується time-only, наприклад годин роботи магазину. Воно стає instant лише після поєднання з датою та timezone.

Timezone database є операційною залежністю

Регіональні правила змінюються політичними рішеннями. Operating system, runtime, container і мобільний клієнт можуть мати різні версії бази timezone. Застарілий клієнт розрахує майбутню подію не так, як оновлений сервер.

Потрібно визначити authoritative компонент і регулярно оновлювати дані. Збереження intended zone дозволяє перерахувати майбутні occurrence після зміни правил.

Тести повинні охоплювати transition boundaries

Перевіряйте зону з daylight saving, зону без нього, дати біля transition, leap day, межу року й історичні значення. Не покладайтеся на default timezone машини — задавайте потрібну зону явно, щоб CI та production мали однаковий результат.

Використовуйте підтримувану date-time бібліотеку й IANA data замість власної таблиці offset. Календарні правила містять більше історичних винятків, ніж може безпечно описати короткий helper.

Історичний час має окремі складнощі

Старі записи могли бути створені з неповною або іншою інтерпретацією timezone. Для юридичних документів та імпортованих архівів варто зберігати початковий текст або metadata джерела, якщо пізніше переосмислення є ризиковим.

Future scheduling та historical reporting є різними задачами. Перша застосовує нові правила вперед, друга іноді повинна відтворити те, що система вважала правильним у минулому.

Показуйте час зрозуміло

Technical interface має включати offset або timezone name там, де можлива неоднозначність. Human interface повинен показувати зону, коли люди координуються між регіонами. Скорочення на кшталт CST не є унікальними identifier.

Для важливих дій confirmation screen має повторити дату, локальний час і controlling timezone. Це дає користувачу шанс побачити неправильне припущення до збереження instant.

Зберігайте значення, яке справді мав на увазі користувач

Розклад потребує політики після зміни правил

Коли timezone database змінюється, майбутня зустріч може отримати інший UTC instant, хоча локальний намір залишився тим самим. Система повинна вирішити, чи автоматично перераховувати майбутні occurrence, повідомляти користувача або фіксувати старий instant.

Для авіарейсів, платежів і юридичних deadline рішення може відрізнятися. Важливо зберігати достатньо даних, щоб пояснити, за якими правилами було створено конкретний момент.

Комунікація між зонами є продуктовою задачею

Користувачу недостатньо технічно правильного timestamp, якщо інтерфейс приховує controlling timezone. Запрошення, reminder і confirmation повинні повторювати зону та, за потреби, показувати локальну конвертацію для отримувача.

Після зміни розкладу повідомлення має чітко сказати, чи змінився локальний час організатора, instant або лише відображення для глядача.

Інтерфейс редагування також повинен показувати наслідок до збереження. Це особливо важливо для recurring events із багатьма учасниками.

Зрозуміле попередження дешевше за виправлення пропущеної зустрічі.

Для масових змін корисно надсилати оновлені календарні запрошення й зберігати audit причини перерахунку.

Обов’язково.

Зберігайте значення, яке справді мав на увазі користувач

Надійна модель відрізняє instant, local date, local time, timezone та duration. Після цього daylight saving стає відомим правилом конвертації, а не випадковою production-помилкою.

Timezone — це частина сенсу розкладу. Втрата цієї інформації не виправляється пізнішим форматуванням timestamp.