
Зона недопонимания
- Translation

Вот некоторые распространенные ошибочные причины, которые я слышал, призывающие не использовать тип timestamp with time zone:
- Я хочу хранить все в формате UTC;
- Я не хочу получать несколько разных часовых поясов из запроса;
- Мы используем специальную библиотеку для обработки часовых поясов;
- Я не хочу тратить дисковое пространство для хранения часового пояса.
Все эти тезисы произрастают из фундаментального непонимания принципов хранения временных данных в базе данных.
Интуитивно, можно предположить, что timestampTZ в настоящее время хранится примерно как:
"2011-06-11 15:53:22 PDT"
То есть к самому времени добавляется информация о часовом поясе. Это далеко не так.
Вместо этого, все временные данные хранятся в виде значений UTC, вне зависимости от того какой тип использовался: timestamp without time zone или же timestamp with time zone. Разница состоит в процессе записи. Если тип данных подразумевает хранение информации о часовом поясе, то всякий раз при сохранении данных они автоматически преобразовываются из локального времени пользователя во время UTC. Когда пользователь запрашивает данные, они преобразовываются из UTC в местный часовой пояс пользователя.
Допустим, Джош живет в Калифорнии (часовой пояс «America / Los_Angeles»). Он добавляет такую строку в таблицу:
INSERT INTO messages ( user_id, message, left_at )
VALUES ( 3, 'Здорово браттело!', '2011-09-27 17:17:25' );
… тогда Брюс, что живет в Филадельфии (часовой пояс «Америки / New_York»), запросив данные, увидит:
user_id | 3
message | Здорово браттело!
left_at | 2011-09-27 20:17:25-04
… а Магнус, который живет в Швеции («Europe / Stockholm»), в свою очередь, получит:
user_id | 3
message | Здорово браттело!
left_at | 2011-09-28 02:17:25+02
Данные хранятся как UTC, но то, что каждый из пользователей видит, завязано на их местном времени.
Timestamp without time zone просто-напросто не производит никаких преобразований, предполагая, что все временные данные принадлежат одному часовому поясу.
Для большинства языков программирования есть смысл оставить обработку временных данных на совести сервера PostgreSQL, а не полагаться на дополнительный программный слой. Со всей ответственностью можно заявить: „Поддержка временных данных в Postgres по праву является эталонной. И в целом, надежнее и современнее, чем в библиотеках для PHP, Python или Perl“. Стоит также отметить, что PostgreSQL прекрасно справляется с проблемами перехода на летнее\зимнее время.
Что еще более важно, использование timestampTZ означает, что вам никогда не придется беспокоиться о написании кода приложения для отображения данных в часовом поясе пользователя. Вместо этого, вам надо просто установить параметр TIMEZONE для сеанса пользователя и временные данные автоматически будут отображаться в соответствующем часовом поясе.
Конечно, есть несколько годных причин не хранить информацию о часовом поясе:
- Ваш драйвер или ORM не поддерживает временные зоны (хотя это может быть аргументом в пользу нового);
- Ваш код должен также работать с СУБД без адекватной поддержки часовых поясов;
- Вы собираетесь секционировать (partitioning) таблицу по колонке с датой и нуждаетесь в абсолютных значениях;
- База данных никогда никогда не будет использоваться более чем в одном часовом поясе.
Но если ни одна из этих причин к вам не относится, то вам следует использовать тип timestampTZ.
Кстати, Альваро Эррера в настоящее время работает над созданием нового дополнительного типа данных, который позволит хранить часовой пояс клиентского приложения, изменившего данные. Этот тип будет востребован в узких кругах, и ни в коей мере не является заменой стандартным темпоральным типам.
Comments 16
Only users with full accounts can post comments. Log in, please.