2014-05-22 3 views
0

Я имею дело с MySQL и Java и с проблемой обработки часового пояса.MySQL и Java и проблема с обработкой часового пояса

Вопрос: Сервер базы данных находится в центральной части США. Пользователь 1 находится в Мексике. Пользователь 2 находится в Сингапуре.

Пользователь 1 вводит дату и время в соответствии с часовым поясом Великобритании, чтобы предоставить информацию о вылете рейса из Лондона.

Пользователь 2 должен быть в состоянии видеть, поданной в любом из ниже 3 вариантов

  1. даты и времени, как введенный пользователем 1 в часовом поясе Великобритании
  2. Дата и время согласно часовому поясу пользователя
  3. Дата и время в соответствии с UTC

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

+0

См. Подобные вопросы [здесь] (http://stackoverflow.com/q/33343893/642706) и [здесь] (http://stackoverflow.com/q/2532729/642706). –

ответ

1

Стремитесь хранить информацию о времени всегда в соглашении UTC. Это единственное, что соответствует 1: 1 «моментами времени», поскольку они «были» в действительности.

Все остальное является проблемой представления/рендеринга.

Сделайте это, даже если вы считаете, что у вас нет проблемы с часовыми поясами. Эта проблема все еще может быть поднята позже в жизненном цикле БД.

+0

Вы бы предложили использовать 2 поля для времени и часового пояса или только для одного? – user3160980

+1

Eurhm, ответ на это находится в ответе. Вы знаете, что такое UTC? –

+0

Привет, Эрвин, я понимаю, что такое UTC. Моя проблема заключается в том, чтобы фиксировать тайминги рейсов. Если человек в Великобритании должен ввести время вылета и прибытия рейса из США в Сингапур, я не могу ожидать, что пользователь перейдет в местный часовой пояс и войдет. Точно так же, если человек в Сингапуре должен увидеть тайминги, время вылета должно быть таким же, как в США, но не в Сингапурское время. Я буду продолжать со временем, сохраненным как UTC, а также часовым поясом, если он отличается от профиля пользователя. – user3160980

0

Правильный номер Answer by Erwin Smout.

Вот пример кода для всех трех ваших случаев и обсуждения.

Тип базы данных TIMESTAMP WITH TIME ZONE

Ваша база данных столбец таблицы должен быть определен в качестве стандартного SQL типа TIMESTAMP WITH TIME ZONE (не WITHOUT). Или что-то подобное в зависимости от вашей базы данных. Поддержка даты-времени варьируется от до между слабыми (SQLite) и надежными (Postgres).

Практически все базы данных фактически сохраняют значения даты и времени в UTC (если они вообще соблюдают часовые пояса). Некоторые сохраняют информацию о часовом поясе, переданную с входными значениями, в то время как некоторые, такие как Postgres, отбрасывают эту информацию после ее использования для настройки значения в формате UTC.

Думают, работа и магазин в UTC

Ваш бизнес-логики и хранения данных должны быть в формате UTC. Таким образом, в UTC есть только одно фактическое время полета. Для различных представительств в Мексике, Сингапуре и Великобритании мы применяем различные временные зоны для перехода на/из значения UTC.

Сервер Ненужные

Расположение сервера в центральной части США должны быть неуместны. Во-первых, серверы должны быть всегда настроены на UTC (или Исландия) для своего часового пояса.Во-вторых, вы должны никогда не зависеть от этого параметра, так как это внешность вне вашего контроля и слишком жутко легко меняться - даже во время работы! Вместо этого всегда указывайте желаемый/ожидаемый часовой пояс в качестве аргументов в коде.

java.time

Всегда используйте java.time классы, никогда java.util.Date/.Calendar/java.text.SimpleDateFormat классы.

java.sql

Получить время полета из базы данных в качестве java.sql.Timestamp, которая находится в UTC по определению.

java.sql.Timestamp ts = myResultSet.getTimestamp(…); 

В рамках старых проблемных классов даты и времени, свести к минимуму использование типов java.sql. Немедленно конвертируйте в классы java.time. Instant - это момент на временной шкале в UTC с разрешением наносекунды.

Instant instant = ts.toInstant(); 

Обратите внимание, что все движущиеся части находятся в формате UTC: хранение базы данных, JDBC, java.sql.Timestamp и Instant. Никаких часовых поясов вообще не возникает.

Adjust для México

Для клиента в Мексике, применить часовой пояс, они выбирают или что вы предполагаете, является целесообразным.

ZoneId zdt_America_MexicoCity = ZoneId.of("America/Mexico_City"); 
ZonedDateTime zdt_America_MexicoCity = ZonedDateTime.ofInstant(instant , zdt_America_MexicoCity); 

Поиск Переполнение стека для получения информации о генерации строк, которые автоматически локализованы на человеческий язык и культурные нормы, используя DateTimeFormatter класс и его ofLocalized… методы.

Adjust для Сингапура

Ditto для клиента в Сингапуре.

ZoneId zdt_Asia_Singapore = ZoneId.of("Asia/Singapore"); 
ZonedDateTime zdt_Asia_Singapore = ZonedDateTime.ofInstant(instant , zdt_Asia_Singapore); 

Все три объекта, наша instant и пара ZonedDateTime объектов, представляют собой же одновременно момент на временной шкале.

Adjust для UTC

Для лица сотрудников авиакомпании, работающих в формате UTC, используйте Instant если все, что нужно для текстового представления является ISO 8601 с 0, 3, 6 или 9 знака после запятой цифры для доли второй.

String output = instant.toString(); 

Если вам нужны другие форматы, как текстовое представление, используйте java.time.format пакет после преобразования Instant к более гибко отформатированный OffsetDateTime класса. Обратите внимание на использование constant for UTC, хранящегося в подклассе ZoneId, ZoneOffset.

OffsetDateTime odt = OffsetDateTime.ofInstant(instant , ZoneOffset.UTC); 

Настройка входных данных

Если пользователь ввода полетного времени в часовом поясе Великобритании, подстраиваться UTC впоследствии. Кстати, не путайте время Великобритании с UTC. Лондонское время изменилось по истории, в настоящее время меняется с летним временем, в то время как UTC никогда не меняется (кроме leap seconds).

ZoneId zoneId_Europe_London = ZoneId.of("Europe/London"); 
ZonedDateTime zdt = ZonedDateTime(2016 , 1 , 3 , 9 , 0 , 0 , 0 , zoneId_Europe_London); 
Instant instant = zdt.toInstant(); 
java.sql.Timestamp ts = java.sql.Timestamp.from(instant); 

Местный

Этот ответ относится к конкретным моментам, на определенную дату и время-день. Если вы имели в виду время полета в смысле «9 AM» на часах на стене, которые могут перемещаться из-за аномалий, включая летнее время (DST), тогда это будет другое обсуждение. В вопросе говорится, что пользователь вводит определенную дату и определенное время, поэтому применяется вышеприведенное обсуждение.

Смежные вопросы