Найкраща практика зберігання DateTime на основі TimeZone


16

Розробка веб-програми, яка повинна дозволяти Користувачеві запланувати зустріч на основі своєї TimeZone. І я зберігаю запланований користувачем datetime як сервер дата в поле бази даних. Під час відображення інформації про графік отримано значення з Бази даних та перетворено у тимчасову зону користувача. обробка в базі коду Я перетворюю DateTime на основі часового поясу користувача. Підкажіть, будь ласка, це найкраща практика чи існує якийсь простий спосіб?

Відповіді:


33

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

Реально, часові позначки слід зберігати у фіксованому єдиному поданні незалежно від того, як вони будуть інтерпретовані, адже як би ви не старалися, у вас завжди будуть неоднозначні випадки, і ви не можете їх вирішити без фіксованого представлення. І ви вибрали один із найгірших випадків використання - розклад зустрічі. Єдиним гіршим випадком загального користування є авіапереліт, коли поїздка може розпочатися в одному часовому поясі і закінчитися в іншому, можливим у більш ранній місцевий час.

Завжди завжди ЗАБЕЗПЕЧАТИ зберігати в UTC та відображати у бажаному або чітко визначеному часовому поясі. Якщо це взагалі можливо, змусіть користувача повідомити вам, у який часовий пояс вони вважають часову позначку, коли вона буде введена ( наприклад , матиме чітке поле часового поясу та попередньо заповнити його бажаною зоною).


1
+1. І її гнучка. Маючи загальний, послідовний, універсальний стандартний контрольний час - будь-яка локальна зона "перенаправлення" буде виконана правильно.
radarbob

Насправді, планування зустрічі - це один з небагатьох випадків, коли ви не можете зберігати його як UTC: Якщо правила DST змінюються (або зміщується від UTC), що відбувається з часом зустрічі? У більшості випадків потрібно, щоб час зустрічі залишався таким же локальним, що означає зміна значення UTC. Ви, швидше за все, захочете зберегти значення, що представляє "TimeInTimeZone + TimeZone", з якого ви могли легко отримати UTC. Планування міжчасового поясу (як і авіакомпанії) має обмеження, які, ймовірно, означають поєднання обох звичок.
Завод-Муза

1
Ох, стає гірше за це. Я регулярно маю зустрічі з колегами в інших країнах, чиї правила зміни часу відрізняються від моїх. Коли це станеться, яка правильна відповідь? Насправді жоден комп’ютер не може знати :-(
Росс Паттерсон

3

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

Якщо дата і час введені користувачем, і сервер не обробляє інформацію про цю дату / час, крім того, щоб зберігати її в базі даних, і не очікується, що введений час адаптується до місця, де його переглядають (наприклад, , користувач ввів "20:00 вечора", і він повинен відображатися як "20:00 вечора" незалежно від того, де в світі він переглядається), тоді найпростішим способом є зберігання DateTime як місцевого часу без будь-якої інформації про часовий пояс.

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


-1 для "зберігати його за місцевим часом", +1 для "зберігати його в UTC".
Росс Паттерсон

@RossPatterson: Чи можете ви пояснити свій '-1 для' зберігати його в місцевий час ''? Мені цікаво, чому це має бути погана ідея, враховуючи умови, які я дав з цим.
Барт ван Інген Шенау

1
Наприклад, використання місцевого часу користувача означає, що кожне значення фактично є одним з кількох десятків різних типів даних. Це означає, що ви не можете цікаво виконувати операції з базою даних над ними, наприклад "TIMESTAMP> '2013-08-27T12: 00: 00'". Це навіть означає, що ви не можете знати, коли і чи слід застосовувати перетворення літнього часу.
Росс Паттерсон

@RossPatterson: Дякую Я погоджуюся, що місцевий час не є правильним рішенням у більшості випадків.
Барт ван Інген Шенау

2

Важливо, щоб ви не поєднували два споріднених поняття.

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

Інша концепція - це "вираз часу", наприклад "20:00 кожного вівторка". Ви спеціально згадали, що дозволяєте людям планувати зустрічі, і якщо у вас повторювані зустрічі, вам потрібно такий вираз. Я не знаю жодної стандартної мови вираження, але що б ви не використовували, це буде відносно часового поясу людини, яка вказала його. Найкраще зробити це чітко, наприклад, "20:00 кожного вівторка в тихоокеанському часовому поясі". У разі вираження часу ви зберігаєте це завжди як рядок і ніколи не залучаєте жодних форматів системного часу.

Дивіться більше обговорення цього питання в моєму блозі


1

Тут багато відповідей вказують на зберігання як UTC. Але будьте дійсно обережні з цим. Наприклад, якщо ви запланували зустріч на 12:00, але зустріч відбудеться після зміни літнього часу, що буде? UTC не зберігає жодної інформації про те, чи був активний dst під час збереження зустрічі. Багато великих, відомих систем зробили цю помилку, коли користувач надсилає електронне повідомлення о 9 ранку влітку, а потім взимку відправлений час показує 8 ранку, тому що обчислення назад від UTC залежить від того, коли ви дивитесь на дату, не увімкнено, коли записано дату.

Набагато краще - припустити, що ваш користувач хоче мати завжди вибраний час. Ні перетворення UTC, ні перетворення часу, ні інформація про часовий пояс, нічого. Записатися на зустріч з 08:00 до 12:00 21 березня 2016 року - це саме так. Не використовуйте ні місцевий час, ні UTC, але не визначений час (у json це не має ні z, ні +, в основному, у .NET це має DateTime.Kind = DateTimeKind.Unspecified).

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

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

На щастя, сюди надходять такі бібліотеки, як http://nodatime.org/, і настійно рекомендуються. Вони працюють з датами набагато послідовніше. Навіть тоді я рекомендую обгортати всі ваші змінні дати та логіку у ваші власні обгортки, використовуючи інтерфейси, щоб їх можна було глузувати, а потім ви все одно можете перемикати логіку пізніше.


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

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

" Таким чином, ви завжди можете обчислити місцевий час на будь-що інше, або на те, що це було б зараз, або на те, що було призначено історично. Тому що часові пояси дуже не статичні, що робить речі ще складнішими " - колись ви приймаєте, що збираєтесь робити розрахунки, вам дійсно потрібно вибрати одне представлення на час. UTC, EST (але не EST5EDT), IST, що завгодно. Але ви просто не можете мати значення, засновані на декількох часових поясах в одному полі, і не робити законної сукупної обробки на них. Обов’язково обробка дисплея. Але це легка частина.
Росс Паттерсон

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