Передовий досвід літнього та часового поясу [закрито]


2046

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

Якщо у вас є що додати, будь ласка, зробіть

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

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

  • Як ви вирішили проблему літнього часу?
  • Які припущення є частиною вашого рішення? (шукаю контекст тут)

Як важливо, якщо не більше:

  • Що ви спробували, що не вийшло?
  • Чому це не вийшло?

Мені було б цікаво програмування, ОС, збереження даних та інші важливі аспекти проблеми.

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


2
@abatishchev - Цей шлях GETDATE()на SQL буде UTC (як буде DateTime.Now). І сервер не матиме ніяких автоматичних змін DST.
Одід

4
@Oded: Я можу погодитись, якщо буде додано "on server". Але все ж це може вплинути на інші програми, які потребують місцевого часу. З цієї та інших причин я думаю, що краще запитати час у Utc чітко.
абатищев

7
UTC є кращим для GMT, як тому, що він більш точно визначений, так і тому, що визначення GMT змішуються в деяких операційних системах. Люди звичайно трактують терміни "GMT" та "UTC" як взаємозамінні, але вони не повністю. Практично для будь-яких цілей програмного забезпечення / систем використовуйте UTC. Дивіться stackoverflow.com/questions/2292334/…
Кріс Джонсон

7
@JoshStodola - Джон Скит в « відповідь ».
Кенні Евітт

1
@ Додано, ви не можете припустити, що сервер буде на UTC, я бачив виробничі сервери, де часовий пояс був "UTC", але застосовано DST, таким чином насправді було UTC + 1 протягом більше півроку. Погодьтеся з @abatishchev бути явним і використовувати, DateTime.UtcNowі GETUTCDATE()він також показує іншим дияволам, що ви насправді про це думали
ono2012

Відповіді:


940

Короткий зміст відповідей та інших даних: (додайте свої)

Зробіть:

  • Щоразу, коли ви маєте на увазі точний момент часу, зберігайте час відповідно до єдиного стандарту, на який не впливає економія денного світла. (GMT і UTC еквівалентні в цьому відношенні, але бажано використовувати термін UTC. Зауважте, що UTC також відомий як зулуський або Z час.)
  • Якщо замість цього ви вирішите зберігати час, використовуючи місцеве значення часу, включіть місцеве зміщення часу для цього конкретного часу від UTC (це зміщення може змінюватися протягом року), таким чином, щоб позначка часу пізніше була однозначно інтерпретована.
  • У деяких випадках вам може знадобитися зберігати як UTC, так і еквівалентний місцевий час. Часто це робиться з двома окремими полями, але деякі платформи підтримують datetimeoffsetтип, який може зберігати обидва в одному полі.
  • Зберігаючи часові позначки як числове значення, використовуйте час Unix - це число цілих секунд з моменту 1970-01-01T00:00:00Z(без урахування високосних секунд). Якщо вам потрібна більш висока точність, замість цього використовуйте мілісекунди. Це значення завжди має базуватися на UTC, без коригування часового поясу.
  • Якщо згодом вам може знадобитися змінити позначку часу, включіть оригінальний ідентифікатор часового поясу, щоб ви могли визначити, чи змінено зміщення від записаного початкового значення.
  • Під час планування майбутніх подій, як правило, кращий місцевий час замість UTC, так як зазвичай відбувається зміщення зміщення. Дивіться відповідь та публікацію в блозі .
  • Під час зберігання цілих дат, таких як дні народження та ювілеї, не перетворюйте на UTC чи будь-який інший часовий пояс.
    • Коли це можливо, зберігайте у типі даних лише для дати, що не включає час доби.
    • Якщо такий тип недоступний, обов’язково завжди ігноруйте час дня при інтерпретації значення. Якщо ви не можете бути впевнені, що час дня буде проігноровано, виберіть 00:00 полудня, а не 00:00 опівночі як більш безпечний репрезентативний час у цей день.
  • Пам'ятайте, що зміщення часового поясу не завжди є цілою кількістю годин (наприклад, індійський стандартний час - UTC + 05: 30, а Непал використовує UTC + 05: 45).
  • Якщо ви використовуєте Java, використовуйте java.time для Java 8 та новіших версій.
  • Якщо ви користуєтесь .NET , розгляньте можливість використання Noda Time .
  • Якщо ви користуєтесь .NET без Noda Time, вважайте, що DateTimeOffsetце часто кращий вибір, ніж DateTime.
  • Якщо ви користуєтеся Perl, використовуйте DateTime .
  • Якщо ви використовуєте Python, використовуйте pytz або dateutil .
  • Якщо ви використовуєте JavaScript, використовуйте moment.js з розширенням моменту-часового поясу .
  • Якщо ви використовуєте PHP> 5.2, використовуйте перетворення нативних часових поясів, передбачені класами DateTime, та DateTimeZoneкласи. Будьте обережні при використанні DateTimeZone::listAbbreviations()- див. Відповідь . Щоб підтримувати PHP з актуальними даними Olson, періодично встановлюйте пакет PECL timezonedb ; див. відповідь .
  • Якщо ви використовуєте C ++, обов'язково використовуйте бібліотеку, яка належним чином реалізує базу даних часового поясу IANA . Сюди можна віднести cctz , ICU та бібліотеку "тз" Говарда Хіннанта .
    • Не використовуйте Boost для перетворень часового поясу. Хоча його API стверджує, що підтримує стандартні ідентифікатори IANA (він же "zoneinfo"), він грубо відображає їх у даних у стилі POSIX, не зважаючи на багату історію змін, які може мати кожна зона. (Також файл вийшов з експлуатації.)
  • Якщо ви використовуєте Rust, використовуйте chrono .
  • Більшість правил ведення бізнесу використовують цивільний час, а не UTC чи GMT. Тому плануйте перетворити часові позначки UTC у локальний часовий пояс, перш ніж застосовувати логіку програми.
  • Пам’ятайте, що часові пояси та компенсації не фіксуються і можуть змінюватися. Наприклад, історично США та Великобританія використовували одні й ті самі дати, щоб «весна вперед» та «падіння назад». Однак у 2007 році США змінили дати зміни годин. Це означає, що за 48 тижнів року різниця між лондонським та нью-йоркським часом становить 5 годин, а за 4 тижні (3 навесні, 1 восени) - 4 години. Будьте в курсі подібних предметів у будь-яких обчисленнях, що стосуються кількох зон.
  • Розглянемо тип часу (фактичний час події, час трансляції, відносний час, історичний час, час, що повторюється), які елементи (часова марка, зміщення часового поясу та назва часового поясу) потрібно зберігати для правильного пошуку - див. "Типи часу" в ця відповідь .
  • Тримайте синхронізацію файлів ОС, бази даних та додатків tzdata між собою та іншим світом.
  • На серверах встановіть годинник обладнання та годинник ОС на UTC, а не на локальний часовий пояс.
  • Незалежно від попередньої точки кулі, код на стороні сервера, включаючи веб-сайти, ніколи не повинен сподіватися, що локальний часовий пояс сервера стане чимось особливим. див. відповідь .
  • Віддайте перевагу роботі з часовими поясами в кожному конкретному випадку в коді програми, а не глобально через налаштування файлів конфігурації або за замовчуванням.
  • Використовуйте сервіси NTP на всіх серверах.
  • Якщо ви використовуєте FAT32 , пам’ятайте, що часові позначки зберігаються за місцевим часом, а не за UTC.
  • Маючи справу з повторюваними подіями (наприклад, щотижневі телешоу, наприклад), пам’ятайте, що час змінюється за допомогою DST і буде різним у часових поясах.
  • Завжди запитувати значення дати та часу як нижня межа включно, верхня межа виключно ( >=, <).

Не:

  • Не плутайте "часовий пояс", наприклад, America/New_Yorkз "зміщенням часового поясу", наприклад -05:00. Це дві різні речі. Дивіться вікі тегів часового поясу .
  • Не використовуйте Dateоб’єкт JavaScript для виконання обчислень дати та часу в старих веб-браузерах, оскільки ECMAScript 5.1 та новіші версії мають вади дизайну, які можуть неправильно використовувати літній час неправильно. (Це було зафіксовано в ECMAScript 6/2015).
  • Ніколи не довіряйте годиннику клієнта. Це може бути невірним.
  • Не кажіть людям "завжди використовувати UTC скрізь". Ця поширена порада коротко бачить декілька дійсних сценаріїв, описаних раніше в цьому документі. Натомість використовуйте відповідні посилання на час для даних, з якими ви працюєте. ( Тимчасові позначки можуть використовувати UTC, але майбутні графіки часу та значення для дати не повинні.)

Тестування:

  • Під час тестування переконайтесь, що ви перевіряєте країни Західної, Східної, Північної та Південної півкулі (адже в кожній чверті земної кулі, тобто 4 регіони), з часом, коли DST працює, а не (дає 8), та країною, яка робить це не використовувати DST (ще 4 для покриття всіх регіонів, загалом 12).
  • Тестовий перехід DST, тобто коли ви перебуваєте в літній час, виберіть значення часу від зимового.
  • Випробування граничних випадків, таких як часовий пояс, що становить UTC + 12, за допомогою DST, що робить місцевий час UTC + 13 влітку і навіть місця, які є UTC + 13 взимку
  • Перевірте всі сторонні бібліотеки та програми та переконайтесь, що вони правильно обробляють дані часового поясу.
  • Принаймні тестуйте півгодинні часові зони.

Довідка:

Інший:

  • Лобіюйте свого представника, щоб припинити гидоту, що є DST. Ми завжди можемо сподіватися ...
  • Вестибюль для стандартного часу Землі

31
Використання GMT насправді не вирішує проблему, вам все-таки потрібно розібратися, яку правильну дельту застосувати, і саме тут полягає вся складність. Дельта може бути складною для визначення в системах, які використовуються користувачами в різних регіонах (з різними графіками перемикання літнього режиму) або в системах, що показують історичні / майбутні дані.
ckarras

10
Це правда, якщо все, що потрібно зробити, це відображати поточний місцевий час. Але якщо у нас є, наприклад, сервер в Австралії, який повинен відображати дату / час транзакції в Канаді 2 квітня 2006 р. (Це був останній рік, перш ніж у Канаді змінилися правила перемикання літнього режиму) - чи маєте ви виклик ОС? що може робити DateTime ("2006/04/02 14: 35Z"). ToLocalTime (). WithDaylightSavingRules ("Канада", 2006)?
ckarras

22
Так, у Windows існує такий виклик ОС - SystemTimeToTzSpecificLocation. msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx
Майкл Мадсен

7
@tchrist Можливо, якщо ти наполегливий, можеш.
Пітер Айтай

16
Майте на увазі, перетворюючи майбутні дати (навіть завтра) в UTC, ви завжди щось втрачаєте. Наприклад, ви використовували деякий відомий зсув для здійснення цієї конверсії, але оскільки дата є в майбутньому, завжди є ймовірність, що група, яка встановлює ці правила, змінить ці правила. Крім того, практично неможливо перетворити деякі майбутні дати в UTC, оскільки час літнього часу не відомий до цього року (деякі країни встановлюють дати щороку, а не на 10+ років вперед або на основі будь-яких встановлених правил).
eselk

319

Я не впевнений, що можу додати до вищезазначених відповідей, але ось кілька моментів від мене:

Типи разів

Ви повинні врахувати чотири рази:

  1. Час події: наприклад, час, коли відбувається міжнародна спортивна подія, або коронація / смерть тощо. Це залежить від часового поясу події, а не від глядача.
  2. Час телебачення: наприклад, конкретне телешоу транслюється о 21:00 за місцевим часом у всьому світі. Важливо, коли розмірковуєте над публікацією результатів (скажімо, American Idol) на своєму веб-сайті
  3. Відносний час: наприклад: Це запитання закривається за 21 год. Це легко відобразити
  4. Повторний час: наприклад: Телевізійне шоу відбувається щопонеділка о 21:00, навіть коли DST змінюється.

Також є історичний / альтернативний час. Вони дратують, оскільки вони не можуть повернутися до стандартного часу. Напр.: Джуліанські дати, дати згідно місячного календаря на Сатурні, Клінгонський календар.

Зберігання часових позначок початку та кінця в UTC працює добре. Для 1 вам потрібна назва часового поясу події + зміщення, збережене разом із подією. Для 2 вам потрібен локальний ідентифікатор часу, що зберігається з кожною областю, і місцеве ім'я часового поясу + зміщення, збережене для кожного глядача (це можливо отримати з IP-адреси, якщо ви стиснулися). Протягом 3 годин зберігайте в UTC секундах і не потрібно часу. 4 - це особливий випадок 1 або 2 залежно від того, глобальна це чи локальна подія, але вам також потрібно зберегти створене в часовій марці, щоб ви могли визначити, чи змінилося визначення часового поясу до або після створення цієї події. Це необхідно, якщо потрібно показати історичні дані.

Зберігання разів

  • Завжди зберігайте час у UTC
  • Перетворити на місцевий час на дисплеї (місцевий визначається користувачем, який переглядає дані)
  • Під час зберігання часового поясу потрібні ім’я, часова марка та зміщення. Це потрібно, тому що уряди іноді змінюють значення своїх часових поясів (наприклад: уряд США змінив дати DST), і ваш додаток повинен грамотно поводитись із речами ... Наприклад: точна мітка часу, коли епізоди LOST відображалися як до, так і після правил DST змінився.

Зсуви та імена

Прикладом вищезазначеного може бути:

Гра в фіналі чемпіонату світу з футболу відбулася в Південній Африці (UTC + 2 - SAST) 11 липня 2010 року о 19:00 UTC.

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

Системний час

Вам також потрібно тримати файли ОС, бази даних та додатків tzdata синхронізовано, як між собою, так і з рештою світу, і під час оновлення проводити велику перевірку. Це не є нечуваним, що стороннє додаток, від якого ви залежите, не впорався із зміною TZ правильно.

Переконайтеся, що апаратні годинники встановлені на UTC, а якщо ви працюєте з серверами по всьому світу, переконайтеся, що їх ОС налаштовані також для використання UTC. Це стає очевидним, коли вам потрібно копіювати щоденно обертові файли журналу apache з серверів у декілька часових поясів. Сортування їх за назвою файлів працює лише в тому випадку, якщо всі файли названі з однаковим часовим поясом. Це також означає, що вам не потрібно робити математику дат у голові, коли ви переходите з одного поля в інше і вам потрібно порівнювати часові позначки.

Також запустіть ntpd у всіх полях.

Клієнти

Ніколи не довіряйте часовій позначці, отриманій від клієнтської машини, як дійсній. Наприклад, заголовки Date: HTTP або Date.getTime()дзвінок javascript . Це добре, якщо вони використовуються як непрозорі ідентифікатори або коли ви робите математику дат під час одного сеансу на тому ж клієнті, але не намагайтеся перехресне посилання на ці значення із тим, що у вас є на сервері. Ваші клієнти не запускають NTP і, можливо, не обов'язково мають батарею, що працює для BIOS-годин.

Дрібниці

Нарешті, уряди іноді роблять дуже дивні речі:

Стандартний час у Нідерландах за законом з 1909-05-01 по 1937-06-30 був рівним на 19 хвилин і на 32,13 секунди попереду UTC. Цей часовий пояс не може бути точно представлений у форматі HH: MM.

Гаразд, я думаю, що я закінчив.


6
У цій відповіді є деякі чудові моменти, я особливо хотів зазначити цю частину "Повторний час: наприклад: Телевізійне шоу відбувається щопонеділка о 21:00, навіть коли DST змінюється" Зберігання разів у UTC в БД, а потім перетворення на дисплей допомагає впоратися. багато складних аспектів поводження з часовими поясами. Однак поводження з "повторюваними подіями", які перетинають бар'єри DST, стає значно жорсткішим.
Джаред Хейлз

45
+1 для дрібниць. Зберігання вмісту цікавим робить це завдання приємнішим, що може призвести до підвищення продуктивності :)
Кріс

4
У цій відповіді багато хорошого матеріалу, але кілька питань. 1) Багато скорочень часових поясів неоднозначні. дивіться тут 2) Не завжди ви хочете зберігати в UTC. Більшість часу - так, але контекст має значення. Згідно з вами, телевізійний час не зберігатиметься в UTC. Крім того, іноді є неправомірною або проти політикою не зберігати місцевий час - саме тут можуть DateTimeOffsetбути корисні такі речі (або їх еквівалент). Інакше добре запишіть.
Метт Джонсон-Пінт

1
Отже, всі згодні з тим, що бібліотека Joda - це найкращий інструмент для роботи. Однак нам потрібно постійно оновлювати (відновлювати) jar jar-файл відповідно до цієї статті ( joda.org/joda-time/tz_update.html ), щоб бути в курсі останніх відомостей про часовий пояс. Чи існує стандартний спосіб завантаження останніх даних часового поясу з веб-сайту IANA ( iana.org/time-zones ) та відновлення бібліотеки joda ? Іншими словами, чи можна автоматизувати цей процес, а не робити це вручну?
saravana_pc

2
Нідерланди дрібниці виглядають законно. ietf.org/rfc/rfc3339.txt розділ 5.8. На півдорозі зрозумів, що хтось тягне нам за ногу.
ruffin

89

Це важливе і напрочуд важке питання. Правда полягає в тому, що не існує повністю задовольняючого стандарту для збереження часу. Наприклад, стандарт SQL та формат ISO (ISO 8601) явно недостатньо.

З концептуальної точки зору зазвичай розглядаються два типи даних про дату часу, і їх зручно розрізняти (вищезазначені стандарти не мають): " фізичний час " та " громадянський час ".

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

"Громадянський" час - це специфікація дати, яка відповідає громадянським нормам: момент часу тут повністю визначається набором полів дати (Y, M, D, H, MM, S, FS) плюс TZ (специфікація часового поясу) (також "календар", насправді; але припускаємо, що ми обмежимо обговорення григоріанським календарем). Часовий пояс і календар спільно дозволяють (в принципі) відображати одне представлення до іншого. Але цивільні та фізичні моменти часу є принципово різними типами величин, і їх слід тримати концептуально розділеними та трактувати по-різному (аналогія: масиви байтів та символьні рядки).

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

Джон записує у свій календар нагадування про якусь подію на дату 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (що змістило GMT-4, отже, воно відповідає UTC 2019-Jul-27 14:30:00). Але через якийсь день країна вирішує змінити зміщення TZ на GMT-5.

Тепер, коли настає день ... чи має це нагадування спрацювати

А) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

або

Б) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

Правильної відповіді немає, якщо тільки ніхто не знає, що Іоанн концептуально мав на увазі, коли він сказав в календарі "Будь ласка, дзвоніть мені 2019-Jul-27, 10:30:00 TZ=Chile/Santiago"

Він мав на увазі "цивільну дату-час" ("коли годинники в моєму місті говорять про 10:30")? У цьому випадку А) - правильна відповідь.

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

Деякі API дати / часу отримують це право розрізнення: серед них Jodatime , який є основою наступного (третього!) Java DateTime API (JSR 310).


1
Ще один момент, на який слід звернути увагу, який я не бачив, звертаючись в API, - це те, що навіть коли задано час та часовий пояс, існують щонайменше два правдоподібних значення, наприклад, "13: 00: 00EDT". Це може бути посилання на те, що, як відомо, сталося о 13 годині за місцевим часом, який, як вважалося, був східним літнім часом, або те, що, як відомо, сталося в той момент, коли східний час вдарив о 13:00, що, як вважають, сталися в місці, яке спостерігало східний літній час. Якщо у вас є багато міток часу, де інформація про часовий пояс може бути невірною (наприклад, файли цифрових камер) ...
supercat

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

3
Очевидно, що Джон хоче A), оскільки люди йдуть на роботу о 8:30, незалежно від поточного часу або часового поясу. Якщо вони перейдуть на DST, вони вийдуть на роботу о 8:30, а коли вийдуть з DST, вони ойдуть на роботу о 8:30. Якщо країна вирішить перейти на інший часовий пояс, вони вийдуть на роботу о 8:30 переддень
Gianluca Ghettini

59

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

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

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

Якщо пов'язані історичні аудиторські зобов’язання (наприклад, точно сказати, коли Джо в Арізонії заплатив рахунок 2 роки тому у вересні), тоді зберігайте для запису як UTC, так і місцевий час (ваші таблиці конвертації змінюватимуться з часом).

Визначте часовий пояс, орієнтований на часовий пояс для даних, що надходять масово, як файли, веб-сервіси тощо. Скажімо, у компанії East Coast є центр обробки даних в Каліфорнії - вам потрібно запитати і знати, що вони використовують як стандарт, а не припускати те чи інше.

Не довіряйте зрушенням часового поясу, вбудованим у текстове подання дати та часу, і не приймайте їх аналізувати та виконувати. Натомість завжди вимагайте, щоб часовий пояс та / або опорна зона були чітко визначені . Ви можете легко отримувати час зі зміщенням PST, але час насправді є EST, оскільки саме цей довідковий час клієнта та записи були просто експортовані на сервер, який знаходиться в PST.


40

Вам потрібно знати про базу даних Olson tz , яка доступна на сайті ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ . Він оновлюється кілька разів на рік, щоб вирішити часто в останні хвилини зміни, коли (і чи потрібно) переходити між зимовим та літнім (стандартний та літній час) часу в різних країнах світу. У 2009 році останнім випуском було 2009; у 2010 році це було 2010n; у 2011 році це було 2011n; наприкінці травня 2012 року реліз був 2012c. Зауважте, що існує набір коду для керування даними та власне даними часового поясу в двох окремих архівах (tzcode20xxy.tar.gz та tzdata20xxy.tar.gz). І код, і дані перебувають у відкритому доступі.

Це джерело назв часових поясів, таких як America / Los_Angeles (та синоніми, такі як US / Pacific).

Якщо вам потрібно відстежувати різні зони, то вам потрібна база даних Olson. Як радили інші, ви також хочете зберігати дані у фіксованому форматі - зазвичай, вибраний UTC - разом із записом часового поясу, в якому дані генерувались. Ви можете розрізняти зміщення від UTC на час та назву часового поясу; це може змінити пізніше. Крім того, знаючи, що це в даний час 2010-03-28T23: 47: 00-07: 00 (США / Тихий океан) може чи не може допомогти вам інтерпретувати значення 2010-11-15T12: 30 - яке, імовірно, вказане в PST ( Тихоокеанський стандартний час), а не PDT (тихоокеанський літній час).

Стандартні інтерфейси бібліотеки С не є страшно корисними для подібних матеріалів.


Дані Олсона перемістилися, частково через те, що AD Olson скоро піде у відставку, а частково через те, що проти супроводжувачів авторських прав був порушений позов щодо порушення авторських прав. Базою даних часового поясу зараз керується під егідою IANA , Інтернету, призначеного для числення в Інтернеті, і на першій сторінці є посилання на "База даних часових поясів" . Список розсилки для обговорень зараз tz@iana.org; список оголошень є tz-announce@iana.org.


12
База даних Olson містить і історичні дані, що робить її особливо корисною для обробки DST. Наприклад, відомо, що значення UTC, що відповідає 31 березня 2000 року, у США не в стандартній лінійці DST, а значення UTC, що відповідає 31 березня 2008 року в США, є.
Джош Келлі

3
Консорціум Unicode веде картування між ідентифікаторами зони Olson томе та ідентифікаторами часового поясу Windows: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Джош Келлі

Оновлене посилання на сторінку Консорціуму Unicode: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Span

Де можна знайти інформацію про розбір файлів Olson? Я хочу скомпілювати його в таблицю db, але не можу зрозуміти, як я повинен читати файли
shealtiel

@gidireich: основна інформація знаходиться в даних, і це не просто зрозуміти. Основна документація на неї знаходиться на zic.8сторінці man (або zic.8.txt). Для отримання цієї інформації вам знадобиться, tzcode2011i.tar.gzа не файл, а також, як і tzdata2011i.tar.gzфайл.
Джонатан Леффлер

26

Загалом, включити локальний зсув часу (включаючи зміщення DST) у збережені часові позначки: одного тільки UTC недостатньо, якщо пізніше ви хочете відобразити часову позначку в початковому часовому поясі (і налаштування DST).

Майте на увазі, що зміщення не завжди є цілою кількістю годин (наприклад, індійський стандартний час - UTC + 05: 30).

Наприклад, придатними форматами є кортеж (час Unix, зміщення в хвилинах) або ISO 8601 .


5
Для відображення компенсація ідеальна. Якщо ви хочете внести зміни, компенсації все одно недостатньо. Ви також повинні знати часовий пояс, оскільки нове значення може вимагати іншого зміщення.
Метт Джонсон-Пінт

23

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

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

У часових поясах не повинно бути повної годинної різниці від GMT. У Непалі +5,45. Є навіть часові пояси +13. Це означає, що:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

все одно, але 3 різні дні!

Також немає чіткого стандарту щодо скорочень часових поясів, і як вони змінюються, коли в DST, щоб ви закінчилися з такими речами:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

Найкраща порада - якомога більше триматися подалі від місцевих часів і дотримуватися UTC, де можна. Перевести лише на місцевий час в останній можливий момент.

Під час тестування переконайтесь, що ви протестуєте країни Західної та Східної півкулі, з типом, що працює за типом ДСТ, а не з країною, яка не використовує DST (загалом 6).


Щодо Ізраїлю - це наполовину вірно. Хоча час зміни DST не є конкретною датою в Юліанському календарі - є правило, засноване на єврейському календарі (зміни відбулися в 2014 році). У будь-якому випадку загальна ідея правильна - це може змінитися і змінитись час від часу
Yaron U.

1
Також AST = атлантичний стандартний час. Що стосується "найкращої поради", то це нормально як вихідний пункт, але вам потрібно прочитати решту цієї сторінки та сказати невелику молитву, і ви можете це зрозуміти на деякий час.
DavidWalley

20

Для PHP:

Клас DateTimeZone в PHP> 5.2 вже базується на БД Olson, який згадують інші, тому якщо ви робите перетворення часових поясів у PHP, а не в БД, ви звільняєтесь від роботи з (важко зрозумілими) файлами Olson.

Однак PHP не оновлюється так часто, як DB Olson, тому просто використання перетворень часових поясів PHP може залишити вас застарілою інформацією про DST та вплинути на правильність ваших даних. Незважаючи на те , що це не повинно було статися часто, це може статися, і буде відбуватися , якщо у вас є велика база користувачів по всьому світу.

Щоб впоратися з вищезазначеною проблемою, використовуйте пакет timezonedb pecl . Його функція - оновлення даних часового поясу PHP. Встановіть цей пакет так часто, як він оновлюється. (Я не впевнений, чи оновлення цього пакета точно відповідають оновленням Olson, але, здається, вони оновлюються з частотою, яка принаймні дуже близька до частоти оновлень Olson.)


18

Якщо ваш дизайн може вмістити його, уникайте перетворення місцевого часу всі разом!

Я знаю, для когось це може здатися божевільним, але думаю про UX: користувачі обробляють близькі, відносні дати (сьогодні, вчора, наступного понеділка) швидше, ніж абсолютні дати (2010.09.17, п’ятниця, 17 вересня) на перший погляд. І якщо ви думаєте про це більше, точність часових поясів (і DST) важливіша, чим ближче до дати now(), тож якщо ви можете виразити дати / дати у відповідному форматі протягом +/- 1 або 2 тижні, решта дати можуть бути UTC, і це не має великого значення для 95% користувачів.

Таким чином, ви можете зберігати всі дати в UTC та робити відносні порівняння в UTC та просто показувати дати UTC користувача за межами вашого відносного порогової дати.

Це також може стосуватися введення користувачів (але, як правило, більш обмеженим способом). Вибір зі спадного списку, який має лише {Вчора, Сьогодні, Завтра, Наступного понеділка, Наступного четверга, для користувача набагато простіший і простіший, ніж вибір дати. Підбирачі дат є одними з найбільш больових компонентів заповнення форми. Звичайно, це не спрацює для всіх випадків, але ви можете бачити, що для створення його дуже потужного потрібен лише трохи розумний дизайн.


16

Хоча я ще не пробував цього, підхід до коригування часового поясу я вважав би переконливим таким:

  1. Зберігати все в UTC.

  2. Створіть таблицю TZOffsetsз трьома стовпцями: RegionClassId, StartDateTime та OffsetMinutes (int, хвилин).

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

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

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

Можливо, ви захочете кешувати цю таблицю у вашому додатку та використовувати LINQ або якісь подібні засоби для виконання запитів, а не звернення до бази даних.

Ці дані можуть бути відігнані з бази даних tz з загальнодоступним доступом .

Переваги та виноски цього підходу:

  1. Жодні правила не вводяться в код, ви можете легко відрегулювати зрушення для нових регіонів або діапазонів дат.
  2. Вам не потрібно підтримувати кожен діапазон дат чи регіонів, ви можете додавати їх за потребою.
  3. У регіонах не повинно відповідати геополітичним кордонам, і щоб уникнути дублювання рядків (наприклад, більшість штатів у США обробляють DST однаково), ви можете мати широкі записи RegionClass, які посилаються в іншій таблиці до більш традиційних списків штати, країни тощо.
  4. Для таких ситуацій, як США, де дата початку та закінчення DST змінилася за останні кілька років, з цим досить легко впоратися.
  5. Оскільки поле StartDateTime також може зберігати час, стандартний час переходу на 2:00 AM обробляється легко.
  6. Не скрізь у світі використовується 1-годинний DST. Це легко вирішує ці випадки.
  7. Таблиця даних є кросплатформою і може бути окремим проектом з відкритим кодом, який може бути використаний розробниками, які використовують майже будь-яку платформу бази даних або мову програмування.
  8. Це можна використовувати для компенсацій, які не мають нічого спільного з часовими поясами. Наприклад, 1-секундні коригування, які час від часу трапляються для регулювання обертання Землі, історичних коригувань до та в межах Григоріанського календаря тощо.
  9. Оскільки це знаходиться в таблиці бази даних, стандартні запити звітів тощо можуть скористатися цими даними без використання коду бізнес-логіки.
  10. Це також обробляє зрушення часового поясу, якщо ви цього хочете, і навіть може враховувати спеціальні історичні випадки, коли регіон присвоюється іншому часовому поясу. Все, що вам потрібно, - це початкова дата, яка призначає зміщення часового поясу для кожного регіону з мінімальною датою початку. Це потребує створення принаймні одного регіону для кожного часового поясу, але дозволить вам задати цікаві питання на кшталт: "Яка різниця в місцевому часі між Юмою, Арізоною та Сіетл, штат Вашингтон, 2 лютого 1989 року о 5:00?" (Просто відніміть один SUM () від іншого).

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


8
Ваша ідея бази даних вже реалізована як база даних Olson. Хоча час на літній час створює перекриття із зазначенням конкретного часового поясу, що може перешкоджати вирішенню проблеми. 2:15 EST та 2:15 EDT - це різні часи. Як зазначається в інших публікаціях, уточнення зміщення також вирішує неоднозначність.
BillThor

5
Великою проблемою у збереженні власної бази даних є постійне оновлення її. Olson та Windows підтримуються для вас. У мене було не один випадок поганих переходів DST, оскільки таблиці застаріли. Витягнути їх повністю і покластись на базу даних на рамках або ОС набагато надійніше.
Метт Джонсон-Пінт

4
Не створюйте власну базу даних : завжди покладайтесь на API системи!
Олексій

15

Нещодавно у веб-додатку виникла проблема, коли під час повернення Ajax час, що повертався до мого серверного коду, відрізнявся від часу, що надходив до дати.

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

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

Моє навчання з цього: не використовуйте обчислення дати та часу JavaScript у веб-додатках, якщо вам АБСОЛЮТНО не доведеться.


Javascript працює на клієнтській машині, а не на серверній машині. Базовим датою Javascript є час дати клієнта, а не дата сервера.
BalusC

Привіт, BalusC. Я розумію це (з мого початкового допису: "сценарій javacode на клієнті, який створив дату ..."). Моя проблема полягала в тому, що певна клієнтська машина обробляла DST в один бік, а на інші - іншим. Тому я перемістив усю цю серверну обробку, щоб запобігти дивності браузера
Joon

@ Joon - і в реалізаціях JavaScript є помилки, які ви не можете виявити або дозволити. Так що так, ніколи не використовуйте обчислення дати ECMAScript на стороні клієнта для важливих речей (хоча в іншому випадку ви можете зробити досить непогану роботу).
RobG

14

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

23 та 25 годин довгі дні - це біль, з якою можна впоратися, як і 8-годинна зміна, яка займає 7 або 9 годин. Проблема полягає в тому, що ви виявите, що кожен клієнт або навіть відділ замовника мають різні створені ними правила (часто без документування) щодо того, що вони роблять у цих особливих випадках.

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

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


6
Моя подруга, медсестра, працює вночі, і вони повинні записати часовий пояс під час переходу на літній час. Наприклад, 2:00 CST проти 2:00 CDT
Джо Філліпс

1
Так, це звичайно: коли ви підраховуєте (громадянське) середньоденне значення, вам доводиться справлятися з днями 23, 24 або 25 годин. Як наслідок, коли ви обчислюєте додавання 1 день, це не додавання 24 години ! По-друге, не намагайтеся створити власний код часового поясу; використовувати тільки системний API. І не забудьте оновити кожну розгорнуту систему, щоб отримати сучасну базу даних часових поясів .
Олексій

12

Для Інтернету правила не такі складні ...

  • Сторона сервера, використовуйте UTC
  • З боку клієнта, використовуйте Olson
    • Причина: компенсація UTC не є безпечною для літнього часу (наприклад, Нью-Йорк - це EST (UTC - 5 годин) - частина року, EDT (UTC - 4 години) - решта року).
    • Для визначення часового поясу на стороні клієнта у вас є два варіанти:
      • 1) мати зону встановлення користувача (безпечніша)
        • Ресурси: Веб-готовий випадок Olson tz HTML і JSON
      • 2) Зона автоматичного виявлення

Решта - це лише UTC / локальне перетворення за допомогою ваших серверів на даному сервері. Можеш йти...


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

12

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

Загальна порада - встановити часовий пояс сервера на UTC. Це дійсно є найкращою найкращою практикою, але вона існує як допомога для додатків, які не відповідають іншим найкращим практикам. Наприклад, служба може записувати в журнал файли з локальними часовими позначками замість часових позначок на основі UTC, створюючи таким чином двозначності під час переходу на перехід на літній час. Якщо встановити часовий пояс сервера на UTC, виправите цю програму. Однак справжнє виправлення полягало б у тому, щоб додаток увійшов у систему за допомогою UTC для початку.

Код на стороні сервера, включаючи веб-сайти, ніколи не повинен сподіватися, що місцевий часовий пояс сервера стане чимось особливим.

У деяких мовах локальний часовий пояс може легко переповзти до коду програми. Наприклад, DateTime.ToUniversalTimeметод у .NET перетворить з локального часового поясу в UTC, а DateTime.Nowвластивість повертає поточний час у локальному часовому поясі. Також Dateконструктор в JavaScript використовує локальний часовий пояс комп'ютера. Існує багато інших подібних прикладів. Важливо практикувати оборонне програмування, уникаючи будь-якого коду, який використовує локальний часовий пояс комп'ютера.

Резервуйте, використовуючи локальний часовий пояс для клієнтського коду, наприклад, настільних програм, мобільних додатків та JavaScript на стороні клієнта.


11

Тримайте ваші сервери на UTC і переконайтесь, що вони налаштовані на ntp або еквівалент.

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


9

Будьте уважні при роботі з часовими позначками, які зберігаються у файловій системі FAT32 - вона завжди зберігається в локальних часових координатах (до яких належить DST - див. Статтю msdn ). На цьому спалили.


Чудова точка. У NTFS немає цієї проблеми, але деякі люди все ще використовують FAT32 - особливо на клавішах USB.
Метт Джонсон-Пінт

7

Ще одне - переконайтеся, що на серверах застосовано оновлений патч економії літнього часу.

У минулому році у нас була ситуація, коли наш час постійно тривав тиждень протягом трьох тижнів для північноамериканських користувачів, хоча ми використовували систему на основі UTC.

Виявляється, врешті-решт це були сервери. Вони просто потребували застосованого сучасного виправлення ( Windows Server 2003 ).


6

DateTimeZone::listAbbreviations()Вихід PHP

Цей метод PHP повертає асоціативний масив, що містить деякі "основні" часові пояси (наприклад, CEST), які самостійно містять більш конкретні "географічні" часові пояси (наприклад, Європа / Амстердам).

Якщо ви використовуєте ці часові пояси та інформацію про їх зміщення / DST, надзвичайно важливо усвідомити наступне:

Схоже, що всі різні зміщення / DST конфігурації (включаючи історичні конфігурації) кожного часового поясу включені!

Наприклад, Європа / Амстердам можна знайти шість разів у результатах цієї функції. Два події (компенсація 1172/4772) - за амстердамський час, що використовується до 1937 року; два (1200/4800) - за час, який використовувався між 1937 та 1940 роками; і два (3600/4800) - за час, що використовується з 1940 року.

Отже, ви не можете покладатися на інформацію про зміщення / DST, повернуту цією функцією, як правильну / в даний час!

Якщо ви хочете знати поточний зсув / DST певного часового поясу, вам доведеться зробити щось подібне:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

5

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


4

Ви використовуєте рамку .NET ? Якщо так, дозвольте познайомити вас із типом DateTimeOffset , доданим із .NET 3.5.

Ця структура містить як a, так DateTimeі зміщення ( TimeSpan), яке визначає різницю між DateTimeOffsetдатою та часом екземпляра та універсальним координованим часом (UTC).

  • DateTimeOffset.NowСтатичний метод повертає DateTimeOffset екземпляр , що складається з поточного (локального) часу, а також локальне зміщення (як визначено в регіональній інформації операційної системи).

  • DateTimeOffset.UtcNowСтатичний метод повертає DateTimeOffsetекземпляр , що складається з поточного часу в UTC (як якщо б ви були в Грінвічі).

Іншими корисними типами є класи TimeZone та TimeZoneInfo .


Це не є рішенням представленої проблеми.
caradrye

4

Тим, хто бореться з цим на .NET , дізнайся , DateTimeOffsetчи TimeZoneInfoварто та / чи варто твого часу.

Якщо ви хочете використовувати часові пояси IANA / Olson або виявити вбудовані типи недостатньо для ваших потреб, ознайомтеся з Noda Time , який пропонує набагато розумніший API дати та часу для .NET.


4

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

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


3
Проблема тут полягає в тому, що цивільний час (він же календарний час) належним чином не представляє жодного моменту часу. Якщо ви користуєтесь підходом секунди від епохи, чи справді ви будете рахуватися за кожну мить, яку пропустили або перемотали за перехід на літній день? Напевно, ні. Основа епохи працює лише проти UTC або якоїсь іншої фіксованої, миттєвої посилання.
Метт Джонсон-Пінт

@MattJohnson Звідси частина "правил бізнесу". Якщо правила говорять про те, що щось трапляється о 2:30 ранку (або в будь-який час), це станеться два рази на один день на рік і ніколи в один день на рік. Ось що очікує замовник, якщо він не уточнить правило.
користувач253751

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

2

Просто хотілося вказати на дві речі, які здаються неточними або принаймні заплутаними:

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

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

Включіть місцеве зміщення часу таким, яким воно є (включаючи зміщення DST) при зберіганні часових позначок.

Часова позначка завжди представлена ​​в GMT і, таким чином, не має зміщення.


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

Так, за винятком компенсацій UTC та GMT зворотне. Наприклад, UTC-0700 - це те саме, що GMT + 0700. Дійсно, все цифрове повинно в цей час використовувати UTC.
Метт Джонсон-Пінт

1
@Matt: ви впевнені, що компенсації UTC та GMT є зворотними? де я можу прочитати про це?
Reto Höhener

Власне, я вважаю, що раніше я помилявся. GMT і UTC самі не перевернуті. Це те, що є реалізації, які показують їх обернено, такі як база даних IANA / Olson / TZDB. Дивіться тут . Інша область, яку ви бачите в зворотному зміщенні, - це функція getTimezoneOffset () JavaScript.
Метт Джонсон-Пінт

@MattJohnson: Це хаки, і їх слід скасувати.
Алікс Аксель

2

Ось мій досвід: -

(Не потрібно жодної сторонньої бібліотеки)

  • На стороні сервера зберігайте час у форматі UTC, щоб усі значення дати / часу в базі даних були в єдиному стандарті незалежно від місцезнаходження користувачів, серверів, часових поясів або DST.
  • На шарі користувальницького інтерфейсу або в електронних листах, що надсилаються користувачеві, потрібно вказати рази відповідно до користувача. З цього питання вам потрібно встановити часовий пояс користувача, щоб ви могли додати це зміщення до значення UTC вашої бази даних, що призведе до місцевого часу користувача. Ви можете або зняти зсув часового поясу користувача, коли він підписується, або ви можете автоматично виявити їх у веб-та мобільних платформах. Для веб-сайтів функція JavaScript getTimezoneOffset () є стандартом, починаючи з версії 1.0, і сумісна з усіма браузерами. (Посилання: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

Це не працює, якщо врахувати зміни DST. getTimezoneOffsetповертає зсув для дати та часу, коли ви її зателефонували. Це зміщення може змінитися, коли часовий пояс переходить на літній час або вимикає його. Дивіться "часовий пояс! = Зміщення" у вікі тегів часового поясу .
Метт Джонсон-Пінт

1
Якщо ви хочете зберегти сигнал тривоги на зразок "зробіть щось о 10:00", ви не можете зберігати його в UTC через зміни DST. Ви повинні зберігати його відносно місцевого часу.
Олексій

2

Відео Тома Скотта про часові пояси на YouTube на каналі Computerphile також має приємний та захоплюючий опис теми. Приклади включають:

  • Самоа (острів у Тихому океані) змінює свій часовий пояс вперед на 24 години, щоб полегшити торгівлю з Австралією та Новою Зеландією,
  • Західний берег , де 2 групи людей дотримуються різних часових поясів,
  • 18 століття змінюється від юліянського календаря до григоріанського календаря (що сталося в 20 столітті в Росії).

1

Власне, kernel32.dll не експортує SystemTimeToTzSpecificLocation. Однак він експортує наступні два: SystemTimeToTzSpecificLocalTime та TzSpecificLocalTimeToSystemTime ...


1

Ніколи не покладайтеся лише на таких конструкторів

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

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


1

Лише один приклад, який доводить, що час обробки - це описаний величезний безлад, і що ви ніколи не можете бути самовдоволеними. У кількох місцях на цій сторінці були проігноровані високосні секунди.

Кілька років тому операційна система Android використовувала супутники GPS, щоб отримати орієнтир часу UTC, але ігнорувала той факт, що супутники GPS не використовують високосні секунди. Ніхто не помітив, поки не було плутанини напередодні Нового року, коли користувачі телефонів Apple і користувачі телефонів Android зробили свої відбитки приблизно за 15 секунд.

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


1
  • Ніколи, ніколи не зберігайте місцевий час без його зміщення за UTC (або посилання на часовий пояс) - приклади того, як не робити цього, включають FAT32 та struct tmв C.¹
  • Зрозумійте, що часовий пояс - це поєднання
    • набір компенсацій UTC (наприклад, +0100 взимку, +0200 влітку)
    • правила, коли відбудеться переключення (яке може змінитися з часом: наприклад, у 1990-х роках ЄС гармонізував перемикання як в останні неділі березня та жовтня, о 02:00 за стандартним часом / 03:00 за тихоокеанським часом; раніше це відрізнялося між країнами-членами).

¹ Деякі реалізації struct tmдій зберігають зміщення UTC, але це не ввійшло в стандарт.


-4

У роботі з базами даних (зокрема, MySQL , але це стосується більшості баз даних), мені було складно зберігати UTC.

  • Бази даних зазвичай за замовчуванням працюють із датою сервера (тобто CURRENT_TIMESTAMP).
  • Можливо, ви не зможете змінити часовий пояс сервера.
  • Навіть якщо ви можете змінити часовий пояс, у вас може бути сторонній код, який очікує, що часовий пояс сервера буде локальним.

Мені було легше просто зберігати дату часу сервера в базі даних, а потім дозволити базі даних перетворити збережений час дати в UTC (тобто UNIX_TIMESTAMP ()) у операторах SQL. Після цього ви можете використовувати дату часу як UTC у своєму коді.

Якщо у вас 100% контроль над сервером і всім кодом, можливо, краще змінити часовий пояс сервера на UTC.


Місцевий час (час сервера) може бути неоднозначним під час переходів літнього часу на "запасний" режим. Користуватися не так, як ви описали. Локальний час сервера може представляти більше одного часу UTC.
Метт Джонсон-Пінт

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