Який допустимий випадок використання TIMESTAMP БЕЗ часової зони?


40

Існує довга і досить з'ясувальна відповідь на відмінності між

  • TIMESTAMP WITH TIME ZONE -vs-
  • TIMESTAMP WITHOUT TIME ZONE

доступні в цьому SO пост . Що я хотів би знати: чи є дійсні випадки використання для фактичного використання TIMESTAMP WITHOUT TIME ZONEчи слід вважати це антитілом.


Це питання ризикує бути закритим, коли він буде "передусім на основі думки". Я намагався дати кілька об'єктивних поглядів у своїй відповіді нижче.
Colin 't Hart

2
Це питання є цілком реальним, кожен тип даних має зовсім інше значення. Тож я б точно не вважав це питання головним чином на основі думки.
Василь Бурк

Відповіді:


29

Про це йдеться в багатьох місцях, але я думаю , що варто відзначити , завжди , коли ми порівняємо timestamp with time zoneз timestamp without time zoneтипами: не зберігає часовий пояс інформацію разом з міткою часу . Що потрібно робити, це зберігати всі дані у часовому поясі UTC, як зазначено в документах :timestamp WITH time zone

Для часової позначки з часовим поясом внутрішньо збережене значення завжди знаходиться в UTC (Універсальний координований час, традиційно відомий як Грінвіч середній час, GMT). Вхідне значення, яке має вказаний явний часовий пояс, перетворюється в UTC за допомогою відповідного зміщення для цього часового поясу. Якщо у вхідному рядку не вказано жодного часового поясу, то він вважається, що він знаходиться в часовому поясі, зазначеному параметром TimeZone системи, і перетворюється на UTC за допомогою зміщення для зони часового поясу.

Деяким вважається дійсним для використання timestamp WITHOUT time zoneв ситуаціях, коли (1) все знаходиться в одному часовому поясі або (2) прикладний шар обробляє часовий пояс і просто зберігає все у певному часовому поясі (як правило, UTC). Але це також вважається анти-шаблоном, простим, оскільки правильним рішенням для (1) є налаштування параметра TimeZone на заданий один часовий пояс для системи, і (2) вже вирішено, оскільки PostgreSQL вже зберігає все в одному часовому поясі (UTC).

Тепер, з тими двома вниз, я можу прийти лише з одним вагомим приводом для використання timestamp WITHOUT time zone. Це коли ви хочете зберігати події в майбутньому, і якесь попередження повинно бути викликане, коли ми дійшли до того часу. Це може бути корисно, timestamp WITH time zoneякщо і лише в тому випадку, якщо правила, визначені законами регіону про часовий пояс, ніколи не змінювалися. Найпоширеніше правило, яке стосується змін щодо прийняття чи не денного енергозбереження (DST).

Наприклад, уявіть, що ви перебуваєте, скажімо, 2013-06-15(ще не в DST) заплануйте якусь подію, яка відбудеться в 2013-01-15 10:00(яка вже буде в DST), і у 2013-06-15вашому регіоні було призначено прийняти DST; але через деякий час уряд змінив правило і сказав, що ваш регіон більше не використовуватиме DST, і раптом ваш запланований час стає 2013-01-15 11:00(замість цього 10:00), що якщо ви використовуєте timestamp WITH time zone, та оновлюйте свої конфігурації TZ. Звичайно, ви також можете помітити, що подібні випадки можна ставити також і за часовим поясом, якщо ви відстежуєте зміни правил у регіонах / часових зонах, які вас цікавлять, та оновлюйте дані про це.

Варто зазначити, що деякі регіони часто змінюють ці правила (наприклад, у Бразилії, деякі штати - не у всій країні - часто змінюються), але в більшості випадків це змінюється дуже раніше, тому ваші користувачі впливатимуть лише на події, заплановані дуже далеко від поточний час.

З усього сказаного, у мене є лише ще одна пропозиція. Якщо у вас є користувачі, журнали чи щось у різних часових поясах, зберігайте часовий пояс, звідки вони надходять, і вибирайте та використовуйте timestamp with time zone. Таким чином, ви можете (1) перетинати події, що відбуваються ближче один до одного для різних джерел (незалежно від їх часових поясів) та (2) показувати початковий час (годинний час) події, що відбулася.


Ви говорите: "Я можу прийти лише з однією вагомою причиною використовувати часову позначку з часовим поясом". Якщо це не помилка друку, то чи справді ви припускаєте, що "часова марка без часового поясу" насправді більш підходяща / менш схильна створювати непорозуміння, ніж "часова мітка з часовим поясом"? Мені це здається контрінтуїтивним.
Маркус Юній Брут

@MarcusJuniusBrutus, вибач за це, справді це був друкарський помилок, і я подумав навпаки ... Перевір редаговану відповідь.
MatheusOl

codeblog.jonskeet.uk/2019/03/27/… глибоко обговорює саме цей сценарій майбутніх подій-правил-можливо змінити (з тим же викладом)
Бені Чернявський-Паскін

17

Так. Існують випадки використання для TIMESTAMP WITHOUT TIME ZONE.

  • У звичайних бізнес-додатках цей тип буде використовуватися лише для:
    • Бронювання майбутніх зустрічей
    • Представлення однакового часу дня в різних часових поясах, таких як полудень 23-го в Токіо та Парижі (два різні моменти години один від одного, однаковий час дня)
  • Для відстеження моментів, конкретних точок на часовій шкалі, завжди використовуйте TIMESTAMP WITH TIME ZONE, а не WITHOUT.

TIMESTAMP WITHOUT TIME ZONEзначення - це не точка на шкалі часу, а не фактичні моменти. Вони представляють приблизне уявлення про потенційні моменти, можливі точки на часовій шкалі в межах приблизно 26-27 годин (діапазон часових поясів по всьому світу). Вони не мають реального значення, поки ви не застосуєте часовий пояс або змістите з-за UTC .

Наприклад: Різдво

Наприклад, скажіть, що вам потрібно записати початок свят / святих днів.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Щоб зафіксувати той факт, що Різдво починається після півночі 25 грудня цього року, нам потрібно сказати 2016-12-25 00:00:00без жодного часового поясу. Рано в день Санти він відвідує Окленд, штат Нью-Йорк, лише після півночі, оскільки це один із самих ранніх опівночі на земній кулі. Потім він просувається на захід, як це станеться наступної півночі, незабаром дістаючись до Філіппін. Потім північний олень рухається в західному напрямку, до півночі досягаючи Індії, що трапляється через кілька годин після цього опівночі Окленда. Набагато пізніше ще є опівночі в Парижі, а ще пізніше опівночі в Монреалі, Каліфорнія. Всі ці візити Діда Мороза трапляються в різні моменти - час , але все відбулося незабаром після півночі, за кожну власну півночі.

Тож запис 2016-12-25 00:00:00без будь-якого часового поясу як початку Різдва є інформативним та законним, але лише невиразним. Поки ви не скажете «Різдво в Окленді» або «Різдво в Монреалі», у нас немає конкретного моменту часу. Якщо ви записуєте фактичний момент кожного разу, коли сани торкаються донизу, ви скористаєтесь, TIMESTAMP WITH TIME ZONEа не WITHOUTтип.

Подібно до Різдва - новорічна ніч. Коли в Нью-Йорку падає бал Таймс Сквер , люди в Сіетлі все ще охолоджують шампанське і готують свої рожеві вечірки . І все-таки ми б записали ідею новорічної миті як 2017-01-01 00:00:00у TIMESTAMP WITHOUT TIME ZONE. На противагу цьому, якщо ми хочемо записати, коли куля впала в Нью-Йорку, або коли люди в Сіетлі підірвали роги, ми б замість цього використали TIMESTAMP WITH TIME ZONE(не WITHOUT) для того, щоб записати ці фактичні моменти, кожні три години один від одного.

Наприклад: Заводські зміни

Іншим прикладом може бути запис політики, яка передбачає час настінного годинника в різних місцях. Скажімо, у нас є фабрики в Детройті, Дюссельдорфі та Делі. Якщо ми скажемо, що на всіх трьох заводах перша зміна починається о 6 ранку з обідньою перервою в 11:30 ранку, це можна було б записати як TIMESTAMP WITHOUT TIME ZONE. Знову ж таки, ця інформація корисна розпливчасто, але не вказує на конкретний момент часу, поки ми не застосуємо часовий пояс. Новий день світає раніше на сході. Тож фабрика Делі буде першою, яка відкриється о 6 ранку. Години пізніше завод Дюссельдорфа починає свою роботу о 6 ранку. Але фабрика Детройту фактично не відкриється до шести годин пізніше, коли станеться її 6 ранку.

Порівнюйте цю ідею (коли загалом починається заводська зміна) історичному факту, коли кожен заводський працівник почав свою роботу в певний день. Годинник - це реальний момент, фактична точка на часовій шкалі. Отже, ми б записували це у стовпці типу, TIMESTAMP WITH TIME ZONEа не WITHOUTтипу.

Отже, так, існують законні випадки використання TIMESTAMP WITHOUT TIME ZONE. Але, на мій досвід роботи з бізнес-додатками, вони відносно рідкісні. У бізнесі ми, як правило, дбаємо про фактичні моменти: коли фактично надійшла рахунок-фактура, коли саме цей договір набирає чинності, в який момент була здійснена ця банківська операція. Тож у таких поширених ситуаціях ми хочемо TIMESTAMP WITH TIME ZONEтипу.

Для більш детальної дискусії дивіться мій відповідь на аналогічне запитання: чи потрібно зберігати часові позначки UTC або місцевий час для змін

Постгрес

Зауважте, що Postgres спеціально ніколи не зберігає інформацію про часовий пояс, вказану при вставці часової позначки.

  • TIMESTAMP WITH TIME ZONE
    • Будь-який заданий часовий пояс або зсув, включений із вхідними даними, використовується для регулювання значення UTC та зберігається. Інформація про пройдену зону / зсув потім відкидається. Думай TIMESTAMP WITH TIME ZONEяк TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • 7 березня цього року в Індії в 12:00 в обід буде встановлено час часу, призначений для UTC, віднімаючи п'ять з половиною годин: 6:30 ранку.
  • TIMESTAMP WITHOUT TIME ZONE
    • Будь-який вказаний часовий пояс або зміщення, включений до вхідних даних, повністю ігнорується.
    • 7 березня цього року в Індії в 12:00 вночі записується як 12:00 7 березня цього року без коригування.

Стандарт SQL ледь не торкається питань типів даних та часу поведінки. Таким чином бази даних варіюються широко в обробці дати-часу.


далі із заводськими (або лікарняними) змінами, кожен, хто працює на могильнику у дні переходу на літній час, буде записано неправильно свої години, це записано без часового поясу ..
Ясен

Я думаю , що є помилка в останньому прикладі: «вхід 12:00 7 березня .. повинен бути" записаний як 12 : 00 »(не 21:00)
TmTron

11

Я хотів би додати до цього ще один погляд, який суперечить значній частині написаного в інших відповідях. На мою думку, timestamp with time zoneє дуже мало вагомих випадків використання, і їх timestamp without time zoneслід загалом віддати перевагу.

По-перше, ви повинні зрозуміти шаблон "UTC скрізь", який, як правило, рекомендується для всіх програм, які не мають особливих вимог. Це просто означає, що ваша програма повинна представляти всі її часові позначки в UTC, скрізь, весь час. Звичайно, ви показуватимете місцеву дату / час користувачам, але ідея полягає в тому, щоб перетворити їх на самій край вашої програми під час надання представлення. Це правильне місце для об'єднання часової позначки UTC (яку ви можете завантажити з бази даних) та часового поясу користувача (який може надходити з браузера) у локальну часову позначку.

Якщо ви дотримуєтеся цього шаблону, тоді timestamp with time zoneце анти-шаблон. Все, що цей тип робить, це змусити PostgreSQL здійснювати перетворення часових поясів під час читання та запису часових позначок на основі TimeZoneзмінної сесії PostgreSQL . Замість того, щоб мати справу з часовими поясами на самих краях вашої програми, ви ввели їх у серце, у саму комунікацію зі своєю базою даних. Ви повинні подбати про те, щоб PostgreSQL завжди був TimeZoneправильно налаштований, додаючи ще одну непотрібну точку збою та плутанини.

А для чого? Якщо ви слідуєте шаблону UTC скрізь, у вашій програмі все одно є часові позначки UTC; тож чому просити вашу базу даних робити перетворення часових поясів на них? Ви можете просто зберігати їх у timestamp without time zoneстовпці та обробляти їх так, як це завжди UTC. Ні перетворень, ні часових поясів, ні ускладнень.


2
Я думаю, що прихильники timestamptz також підтримують схему "UTC скрізь". Це лише правило, що застосовується на рівні бази даних, а не покладатися лише на розробників додатків / API для його застосування? Якщо ви можете застосувати цю практику, чому б ні? Крім того, ви можете просто встановити, що всі з'єднання постгресів встановлюють часовий пояс на UTC. Навіть якщо цього немає, формат ISO містить зміщення tz. Так чи не те саме, що UTC скрізь, але примусово застосовується?
iamnat

3
По-перше, якщо для вашого PostgreSQL TimeZone встановлено що-небудь, крім UTC, і ви використовуєте timestamptz, ваша програма читає часові позначки, що не є UTC. Це просто не "UTC скрізь", і залежно від мови вашого клієнта може або не може створити багато ускладнень. Або ти всюди UTC, або ти використовуєш місцеві часові позначки ....
Шай Роянський

По-друге, ще раз, якщо у вашій програмі ви всюди UTC, просто немає жодного зрушення для надсилання у форматі ISO для ваших часових міток. Специфікація буде залежати від різних мов, але в ідеалі ви повинні використовувати тип клієнта, який не може представляти нічого, крім часової позначки UTC (наприклад, Instanceв NodaTime / JodaTime). Ви в основному описуєте ситуацію, коли "UTC скрізь" майже дотримується або
ніби

Ще раз, дуже легко уявити, що новий екземпляр PostgreSQL встановлюється на якомусь сервері, випадково зберігаючи часовий пояс локальної машини, який налаштований за замовчуванням. Програми читають з цього сервера і отримують локальні часові позначки в абсолютно довільному часовому поясі (у якому він трапляється). Чому ми хотіли б цього додаткового ускладнення?
Шай Роянський

1
Це могло б, але тоді було б ще менше сенсу використовувати timestamptz. Вся суть цього типу полягає у виконанні перетворень часових поясів у вигляді значень, прочитаних та записаних на PostgreSQL (внутрішньо в базі даних часові позначки завжди зберігаються як UTC). Завжди встановлення часового поясу сеансу на UTC ефективно відключає ці конверсії, так навіщо timestamptzвзагалі використовувати ? По-іншому, якщо значення в базі даних є UTC, а значення, що надходять та виходять із бази даних, завжди є UTC, то чому взагалі у вашій базі є обізнаність про часовий пояс?
Шай Роянський

2

dateМітка часу також не включає в себе інформацію про тимчасових зонах, тим НЕ менш, багато людей використовують його.

Звичайно, саме по собі це не відповідь.

Це дійсно для використання timestampта dateдля будь-яких часових позначок і дат, які завжди знаходяться в одному часовому поясі або зберігаються відносно деякого відомого часового поясу.

Якщо часовий пояс завжди однаковий або неявний, то його більше антипатернів зберігати, ніж не зберігати (зайва інформація).

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


І навпаки, якщо ви проектуєте або працюєте в розподіленій системі або в будь-якій системі, де частини системи будуть розподілені по різних часових поясах, це може вважатися антидіаграмою, яку не слід використовувати timestamp with timezone, хоча деякі системи можуть бути розроблені для роботи в одному часовому поясі, наприклад, UTC. У цьому випадку логіка часового поясу може бути висунута в рівень програми, але я вважаю це антидіаграмою, так.


Я розумію, що в деяких випадках використовувати це не зашкодить timestamp without timezone, але чи купує він мені що-небудь? В іншому випадку, чому я повинен турбуватися, якщо timestamp with timezone dataтип завжди однаковий або більш підходящий?
Маркус Юній Брут

Не зберігання зайвої інформації було б моїм головним аргументом. Я припускаю, що арифметика дати timestamp without timezoneтакож буде швидшою, але це, мабуть, важливо лише, якщо ви обробляєте мільярди рядків ...
Colin 't Hart

1
@ Colin'tHart timestampі timestamptzобидва зберігаються однаково. Інформація про часовий пояс не зберігається в timestamptz, але натомість вона перетворюється на UTC для зберігання. Я б сказав, завжди використовуйте, timestamptzколи зазначені часові позначки позначають абсолютний час . Це все, що timestamptzозначає. Я писав про це тут .
fphilipe

2

Можливо, здається, що зберігати та обробляти дати / часи за місцевим часом, якщо ваша програма обмежена одним часовим поясом, але я вважаю, що це помилка.

При переході назад від літнього часу до стандартного часу на годину за місцевим часом повторюється (припустимо, що різниця становить годину). Там, де я живу, це зазвичай буває близько 2 ранку, тому місцевий час працює 01:58, 01:59, 01:00 і рухається лише до 02:00 наприкінці повторної години.

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

Для порівняння, у UTC немає цієї проблеми і чисто замовляє. Отже, навіть працюючи лише з одним часовим поясом, ви хочете, щоб БД зберігала та обробляла часи в UTC та перетворювалась на / з місцевого часу для введення / відображення. Така поведінка TIMESTAMP З ЧАСОВОЮ ЗОНОЮ.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.