2015-06-04 8 views
7

У меня есть java.time.OffsetDateTime, который я бы хотел конвертировать в java.sql.Timestamp. Поскольку Timestamp не хранит информацию о смещении, я собираюсь хранить все даты/время в базе данных как UTC.Convert OffsetDateTime to UTC Timestamp

Как мне преобразовать OffsetDateTime в Timestamp, который находится в UTC?

EDIT:

Я считаю, что это ответ, но это кажется довольно запутанным способ тайного к UTC:

OffsetDateTime dateTime = OffsetDateTime.now(); 
Timestamp timestamp = Timestamp.valueOf(dateTime.atZoneSameInstant(ZoneId.of("Z")).toLocalDateTime()); 

ответ

7

Это был бы способ сделать преобразование и обеспечить использование UTC. Я думаю, что это немного чище, чем предлагаемое решение с использованием секунд эпохи.

Timestamp test = Timestamp.valueOf(entityValue.atZoneSameInstant(ZoneOffset.UTC).toLocalDateTime()); 
+0

Это неправильно. Если 'dateTime' содержит' 2015-10-23T12: 44: 43Z', и вы находитесь во временной зоне UTC + 2, тогда 'timestamp' будет удерживать' 2015-10-23 14: 44: 43.0' и отличается от результата, предоставленного решение в ответе ('2015-10-23 12: 44: 43.0'). – rve

+0

Да, Timestamp.from (мгновенно), похоже, преобразует его в локальный часовой пояс. Другой способ сделать это и убедиться, что он остался в UTC, - «Timestamp test = Timestamp.valueOf (entityValue.atZoneSameInstant (ZoneOffset.UTC) .toLocalDateTime()); Я отредактировал ответ выше, чтобы отразить это. – Notso

+1

Чтобы прояснить приведенные выше комментарии для использования в будущем: Ранее мой ответ предположил, что Timestamp.from (entityValue.toInstant) сделает это. Однако, хотя мгновение - это по существу мгновение на временной шкале от эпохи, Timestamp.from (мгновенно) возвращает его в ваш местный часовой пояс, как отметил @rve. Таким образом, способ сделать это и убедиться, что он остался в UTC, это «Timestamp test = Timestamp.valueOf (entityValue.atZoneSameInstant (ZoneOffset.UTC) .toLocalDateTime()); – Notso

2

Используйте .toEpochSecond(), чтобы получить # секунд от контрольной даты (который находится в UTC), умножьте на 1000 и передайте это в конструктор Timestamp (так как он ожидает миллисекунды).

new Timestamp(1000 * offsetDateTime.toEpochSecond()); 
+0

Это потеряет информацию о наносекундах, хотя - правильно? – Cheetah

+0

Да, может быть, ваш собственный ответ лучше. – Glorfindel

3

Другим решением было бы:

Timestamp.valueOf(LocalDateTime.ofInstant(dateTime.toInstant(), ZoneOffset.UTC)); 

Он преобразует dateTime в UTC, раздевает информацию часового пояса, а затем преобразует результат в Timestamp. Он все еще запутан, но ИМХО немного чище.

Просто используя toInstance() или toEpochSeconds(), отрегулируйте результат с предоставленным смещением.

Ниже приведены результаты испытаний от этого и другие ответы:

OffsetDateTime dateTime = 
    OffsetDateTime.of(2015, 10, 23, 12, 44, 43, 0, ZoneOffset.UTC); 
    // OffsetDateTime.of(2015, 10, 23, 12, 44, 43, 0, ZoneOffset.ofHours(-5)); 

err.println("dateTime   = " 
    + dateTime 
); 

err.println("as LocalDateTime = " 
    + dateTime.toLocalDateTime() 
); 

err.println("as timestamp (mine) = " 
    + Timestamp.valueOf(LocalDateTime.ofInstant(dateTime.toInstant(), ZoneOffset.UTC)) 
); 

err.println("@Cheetah (correct) = " 
    + Timestamp.valueOf(dateTime.atZoneSameInstant(ZoneId.of("Z")) 
     .toLocalDateTime()) 
); 

err.println("@Notso (wrong)  = " 
    + Timestamp.from(dateTime.toInstant()) 
); 

err.println("@Glorfindel (wrong) = " 
    + new Timestamp(1000 * dateTime.toEpochSecond()) 
); 

, который дает следующие результаты (мой часовой пояс является CET):

(with ZoneOffset.UTC) 
dateTime   = 2015-10-23T12:44:43Z 
as LocalDateTime = 2015-10-23T12:44:43 
as timestamp (mine) = 2015-10-23 12:44:43.0 
@Cheetah (correct) = 2015-10-23 12:44:43.0 
@Notso (wrong)  = 2015-10-23 14:44:43.0 
@Glorfindel (wrong) = 2015-10-23 14:44:43.0 

(with ZoneOffset.ofHours(-5)) 
dateTime   = 2015-10-23T12:44:43-05:00 
as LocalDateTime = 2015-10-23T12:44:43 
as timestamp (mine) = 2015-10-23 17:44:43.0 
@Cheetah (correct) = 2015-10-23 17:44:43.0 
@Notso (wrong)  = 2015-10-23 19:44:43.0 
@Glorfindel (wrong) = 2015-10-23 19:44:43.0 

(версия от Notso выше была до его редактирования от 17 февраля 2016 года)