Следует ли устанавливать в PHP таймзону, соответствующую пользователю?

Привет! <br/> Я ознакомился с множеством статей по этой теме и примерно понимаю систему хранения времени в формате UTC, но у меня есть несколько вопросов для уточнения. <br/> <br/> Ситуация следующая: сервер работает в Москве, а его пользователи находятся по всей стране. Каждый пользователь имеет возможность установить свою <i>личную временную зону</i> (далее - <b>ЛВЗ</b>) в личном кабинете. <br/> <br/> Вот мои вопросы: <br/> 1) Должен ли я устанавливать ЛВЗ пользователя в функции date_default_timezone_set() в PHP приложении, работающем на Bootstrap? Не приведет ли это к тому, что будут затронуты другие подсистемы, такие как логирование? <br/> <br/> 2) Является ли нормой установка временной зоны по умолчанию в UTC для базы данных MySQL? <br/> <br/> 3) Следует ли использовать тип TIMESTAMP для хранения времени в базе данных в формате UTC и установить временную зону в Bootstrap на значение, равное ЛВЗ пользователя? Дата будет сохраняться в базу в соответствии с тем, как ее ввел клиент. Но, учитывая предыдущий вопрос, могут ли возникнуть расхождения в зонах в разных частях приложения? <br/> <br/> 4) Возможно ли использовать тип DATETIME, при этом всегда конвертируя дату из ЛВЗ в UTC при сохранении и выборке данных? <br/> <br/> 5) Какие основные недостатки использования унифицированного временного штампа в формате unixtimestamp? Не приведет ли это к необходимости преобразования в тип даты при выполнении выборок, когда требуются специфичные функции работы с датами? (Насколько сложно это преобразование, учитывая, что DATETIME также хранится как число?)
  • 31 января 2025 г. 11:14
Ответы на вопрос 2
Ответы на ваши вопросы касаются управления временными зонами в приложениях, и они очень актуальны для разработки программного обеспечения, особенно если пользователи находятся в разных временных зонах.

1. **Личная временная зона (ЛВЗ) пользователя и `date_default_timezone_set()`**: Установка временной зоны для `date_default_timezone_set()` на уровне приложения может затронуть глобальное состояние вашего приложения. Если у вас есть разные подсистемы, использующие время, такие как логирование, вам нужно будет убедиться, что они тоже корректно работают с этой временной зоной. Поэтому лучше использовать ЛВЗ пользователя только в тех местах, где это действительно необходимо (например, при отображении даты и времени), и оставить временную зону сервера или UTC для логирования и других внутренних задач.

2. **Временная зона по умолчанию в UTC для MySQL**: Да, установка временной зоны базы данных MySQL в UTC считается нормой и хорошей практикой. Это обеспечивает унификацию хранения времени и уменьшает вероятность ошибок при работе с различными временными зонами. 

3. **Использование типa TIMESTAMP и ЛВЗ**: TIMESTAMP в MySQL хранит время в UTC, что является удобным решением. Вы можете сохранять дату в формате UTC, и затем конвертировать её в ЛВЗ пользователя только при выборке данных для отображения. Это позволит избежать расхождений, так как все операции будут производиться с одним стандартом (UTC).

4. **Использование типа DATETIME и конвертация времени**: Да, можно использовать тип DATETIME и конвертировать время из ЛВЗ в UTC при сохранении и обратно при выборке. Это потребует дополнительной логики преобразования, но позволяет сохранить привычный для разработчиков стиль работы с временными зонами.

5. **Недостатки использования unixtimestamp**: Unixtimestamp (или UNIX-время) представляет собой целое число, что делает его простым для хранения и быстрого выполнения операций. Однако, это также требует дополнительного преобразования в более понятный формат для работы с датами. Например, это может затруднить использование специфичных функций работы с датами и временем в SQL, которые могут не поддерживать UNIX-формат. Преобразование обратно в формат даты является несложным, но может потребовать дополнительных вычислительных затрат и усложнить читаемость запросов.

Подводя итог, рекомендуется использовать UTC для хранения времени и вести конвертацию в ЛВЗ пользователя только на уровне представления данных. Это позволит избежать множества потенциальных проблем с временными зонами и обеспечит консистентность данных в приложении.
Проблем с временными зонами вообще не будет, если их представление выдавить максимально ближе к модели представления данных на интерфейсе пользователя. 
Нужно конвертировать в строку только непосредственно перед отрисовкой дату и время из UTC, и обратно загонять время в UTC, если забираете пользовательский ввод.
Весь бек должен работать в одной временной зоне, а от пользователя знать, что он в такой-то временной зоне, только в контексте сессионной переменной, если это необходимо.
Похожие вопросы