Ramakrishna.Pathuri Ответов: 1

Сохранение и отчетность информации о датах и часовых поясах в базе данных, когда данные зависят от даты и времени


Было довольно много вопросов о сохранении информации о датах и часовых поясах в БД, но больше на общем уровне. Здесь я хотел бы обратиться к конкретному случаю.

Технические характеристики системы

У нас есть база данных CRM системы

Это мультитенантная система, в которой арендаторы могут использовать настройку своего часового пояса (это установка только одного часового пояса для каждого арендатора, сохраненного в таблице арендаторов один раз и никогда не изменяющегося)

- Все временные метки, сохраненные в UTC в БД
- Бизнес-правило должно быть охвачено в БД
- Когда арендатор помещает запись в систему, дата записи вычисляется на основе их локального DateTime и преобразуется в UTC, сохраненный в базе данных.

Мы также хотим иметь возможность выбирать все вызовы на системном уровне, размещенные между некоторыми датами UTC независимо от арендатора (для общей системной статистики/отчетности)

Наша первоначальная идея

Наша первоначальная идея состояла в том, чтобы сохранить UTC DateTime во всей БД и, конечно же, сохранить смещение часового пояса арендаторов относительно UTC и иметь приложение, которое потребляет БД, всегда преобразует даты в UTC, чтобы сама БД всегда работала с UTC.

Способ 1

Сохранение локальных арендаторов DateTime было бы неплохо для каждого арендатора но тогда у нас есть проблема с такими запросами как:

Выберите * из вызовов WHERE OrderDateTime между UTCDateTime1 и UTCDateTime2

Это проблематично, потому что callDateTime в этом запросе означает другой момент времени, основанный на клиенте. Конечно, этот запрос может включать в себя соединение с таблицей арендаторов, чтобы получить локальное смещение даты и времени, которое затем вычислит callDateTime на лету, чтобы внести коррективы. Это возможно, но не уверен, что это хороший способ сделать это?

Способ 2

С другой стороны, при сохранении UTC DateTime, то когда мы делаем расчет количества звонков, так как день/месяц/год в UTC может отличаться от того, что в локальном DateTime

Возьмем крайний пример: допустим, арендатор опережает UTC на 6 часов, а его локальная дата-время-2017-01-01 02:00. UTC будет 2016-12-31 20:00. Заказ, размещенный в этот момент, должен получить звонки, но если сохранить UTC, то он получит 2016-12-31.

В этом случае в момент создания вызовов в БД мы должны получить UTC datetime, смещение арендаторов и скомпилировать дату вызова на основе пересчитанного локального времени арендаторов, но все равно сохранить столбец DateTime в UTC.

мой вопрос

- Каков предпочтительный способ справиться с подобной ситуацией?

- Есть ли хорошее решение с сохранением времени UTC, потому что это было бы довольно хорошо для нас из-за отчетности на системном уровне?

- Если вы идете с сохранением UTC, является ли метод 2) хорошим способом справиться с этими случаями или есть какой-то лучший/рекомендуемый способ?

- Как запросить звонки в период с 20 августа 2019 года по 30 августа 2019 года? ( Здесь дата всегда арендатор часовой пояс даты )

- Как запросить почасовое количество звонков 20 августа 2019 года ? ( здесь дата всегда дата часового пояса арендатора )

- Как создать ежедневный отчет, основанный на дне часового пояса пользователя?

Что я уже пробовал:

мы используем СПС(хранится закупает) получать данные между двумя датами, но результаты будут не точными.

Richard MacCutchan

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

Maciej Los

Звучит как ответ ;)

Richard MacCutchan

Почти, ха-ха.

Maciej Los

Я почти уверен, что нет-почти, но полностью.
Пожалуйста, смотрите мой ответ.

Richard Deeming

NB: Если ваши временные метки могут представлять даты в будущем, убедитесь, что вы знаете о проблемах с их хранением в формате UTC:
Хранение UTC-это не серебряная пуля | блог кодирования Джона Скита[^]

1 Ответов

Рейтинг:
10

Maciej Los

Начальное примечание: Я думаю, что ответ на ваш вопрос основан только на мнении и опыте.

Цитата:
- Каков предпочтительный способ справиться с подобной ситуацией?

Ну, есть два возможных способа хранения дат в базе данных:
1) время UTC
или
2) Дата-Время + Смещение
Второй метод рекомендован мной по самой важной причине:
Цитата:
Структура DateTimeOffset представляет собой значение даты и времени вместе со смещением, которое указывает, насколько это значение отличается от UTC. Таким образом, значение всегда однозначно идентифицирует один момент времени.


Приведенный ниже пример объясняет это лучше, чем тысячи слов:
DateTimeOffset date1 = DateTimeOffset.Now;
DateTimeOffset  date2 = DateTimeOffset.UtcNow;
int diff = ((TimeSpan)(date1 - date2)).Hours;
Console.WriteLine("client time: {0} | utc time: {1} | hour difference: {2}", date1, date2, diff);
//result:
//client time: 2019-08-21 12:44:53 +02:00 | utc time: 2019-08-21 10:44:53 +00:00 | hour difference: 0


Если вы хотите использовать время UTC и правила adjustmant, я должен предупредить вас:
Цитата:
Точная информация о часовом поясе, требуемая приложением, может отсутствовать в конкретной системе по нескольким причинам:
  • Часовой пояс никогда не был определен в реестре локальной системы.
  • Данные о часовом поясе были изменены или удалены из реестра.
  • Часовой пояс не содержит точной информации о корректировках часовых поясов за определенный исторический период.

    Для получения более подробной информации, пожалуйста, смотрите:
    Создание часовых поясов с правилами регулировка | Майкрософт документы[^]
    Выбор между DateTime, DateTimeOffset, TimeSpan и TimeZoneInfo | Microsoft Docs[^]

    Цитата:
    - Есть ли хорошее решение с сохранением времени UTC, потому что это было бы довольно хорошо для нас из-за отчетности на системном уровне?
    - Если вы идете с сохранением UTC, является ли метод 2) хорошим способом справиться с этими случаями или есть какой-то лучший/рекомендуемый способ?
    - Как запросить звонки в период с 20 августа 2019 года по 30 августа 2019 года? ( Здесь дата всегда арендатор часовой пояс даты )
    - Как запросить почасовое количество звонков 20 августа 2019 года ? ( здесь дата всегда дата часового пояса арендатора )
    - Как создать ежедневный отчет, основанный на дне часового пояса пользователя?

    Если вы хотите выбрать UTC, пожалуйста, прочтите комментарий Ричарда к этому вопросу. Он уже ответил на эти вопросы.


    MadMyche

    +5

    Maciej Los

    Спасибо.

    Richard MacCutchan

    Отличное подробное объяснение.

    Maciej Los

    - Спасибо, Ричард.
    :большой палец вверх: