Наше мнение

Почему ошибки с часовыми поясами обычно проблема тестирования, а не данных

Ошибка с часовым поясом почти никогда не проявляется в обычный вторник. Она проявляется именно в ту неделю, когда происходит переход на летнее или зимнее время, или в регионе, правительство которого только что изменило правила смещения почти без предупреждения, или точно на границе двух поясов, где пограничный случай в сопоставлении координат с поясом выбирает не ту сторону. Весь остальной год код, плохо обрабатывающий часовые пояса, работает без каких-либо видимых проблем, и именно это делает такие ошибки настолько живучими: сбой редок по самой своей природе, поэтому его редко замечают, пока он действительно не произойдёт в production.

Мы считаем, что в большинстве таких ошибок винят данные, хотя на самом деле это пробел в тестировании. База данных часовых поясов IANA, на которой основана большая часть серьёзной работы с часовыми поясами, включая нашу, отслеживает эти переходы и изменения правил по мере их появления. Но доступность данных не то же самое, что правильная проверка приложением тех ветвей кода, которые выполняются только в неделю перехода или применяются только к немногим регионам с необычными правилами. Если набор тестов никогда не моделирует границу перехода на летнее время или никогда не выполняет поиск для региона с нестандартным смещением в полчаса или 45 минут, правильность исходных данных не спасёт приложение от ошибки, которую может предотвратить только его собственная непротестированная ветвь кода.

Это тот случай, когда исправление скучное и конкретное, а не захватывающее: тестируйте явно на календарных датах, когда происходят переходы, а не только на произвольной дате, выбранной потому, что так было удобно. Намеренно тестируйте на нескольких пограничных регионах с необычными смещениями, а не только на распространённых часовых поясах с круглыми значениями, в которых обычно и ведётся разработка. Ничего из этого не требует новых данных. Это требует решения, что редкую неделю стоит тестировать так же тщательно, как обычную, поскольку именно в редкую неделю ошибка и проявится у реального пользователя.

Есть и связанная ловушка, которую стоит назвать: однократное кэширование смещения часового пояса для местоположения и бессрочное повторное использование этого кэшированного значения. Смещение, верное в июле, может оказаться неверным в декабре, после того как его сдвинет переход на зимнее время, и кэш, который этого не учитывает, будет уверенно выдавать устаревший ответ без каких-либо признаков того, что что-то пошло не так. Это тоже не проблема качества данных. Это архитектурное решение, исходившее из того, что факт останется неизменным, хотя сама природа этих данных в том, что периодически он меняется.

Мы относим наш эндпоинт часовых поясов к тем частям продукта, которые полностью работают, потому что исходные справочные данные активно поддерживаются, а логика поиска построена так, чтобы напрямую учитывать эти переходы, а не предполагать статичное смещение. Более общая мысль применима не только к нашему продукту: ошибка с часовым поясом, дошедшая до клиента, редко доказывает, что исходные данные были неверны. Гораздо чаще она доказывает, что никто не написал тест для той единственной недели в году или того единственного региона, где правила действительно меняются.