Как конвертировать ZonedDateTime в дату?
Я пытаюсь установить серверное агностическое время даты в моей базе данных, и я считаю, что лучшая практика для этого-установить UTC DateTime. Мой сервер БД-Cassandra, и драйвер БД для Java понимает только тип даты.
Итак, предполагая, что в моем коде я использую новый Java 8 ZonedDateTime, чтобы получить UTC сейчас (ZonedDateTime.now(ZoneOffset.UTC)
), Как я могу преобразовать этот экземпляр ZonedDateTime в класс даты "legacy"?
8 ответов
вы можете конвертировать ZonedDateTime в мгновение, которое вы можете использовать непосредственно с датой.
Date.from(java.time.ZonedDateTime.now().toInstant());
tl; dr
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
хотя в этом коде выше не было смысла. Оба!--7--> и Instant
представляют момент в UTC, всегда в UTC. Код выше имеет тот же эффект, что и:
new java.util.Date() // Capture current moment in UTC.
нет пользы здесь для использования ZonedDateTime
. Если у вас уже есть ZonedDateTime
, настроить на UTC, извлекая Instant
.
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
Другой Ответ Правильный
на ответ by ssoltanid правильно адресует ваш конкретный вопрос, как преобразовать java новой школы.объект времени (ZonedDateTime
) к старой школе java.util.Date
, вы можете пройти java.util.Date
экземпляр (не путать с java.sqlDate
). Так что вы могли бы сделать j.u.Дата из этого instantTruncatedToMilliseconds
в коде выше.
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
если делать это часто, вы можете сделать один лайнер.
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
но было бы аккуратнее создать небольшой метод полезности.
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
обратите внимание на разницу во всем этом коде, чем в вопрос. Код вопроса пытался скорректировать время зона экземпляра ZonedDateTime в формате UTC. Но в этом нет необходимости. Концептуально:
ZonedDateTime = Мгновенный + ZoneId
мы просто извлекаем мгновенную часть, которая уже находится в UTC (в основном в UTC, прочитайте класс doc для точных деталей).
о java.время
на java.время framework встроен в Java 8 и более поздние версии. Такие занятия вытеснить надоедливых старых наследие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
на Joda Времени, теперь режим обслуживания, советует миграцию в java.время классы.
чтобы узнать больше, см. В Oracle Учебник. И переполнение стека поиска для многих примеры и объяснения. Спецификация JSR 310.
вы можете обменять java.время объекты непосредственно с вашей базой данных. Используйте драйвер JDBC соответствуют JDBC 4.2 или позже. Нет необходимости в строках, нет необходимости в java.sql.*
классы.
где получить java.время занятий?
-
Java SE 8, Java SE 9, Java SE 10, и позже
- встроенный.
- часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
-
Java SE 6 и Java SE 7
- большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
-
Android
- более поздние версии Android bundle реализации java.время классы.
- для более раннего Android (ThreeTenABP проект приспосабливается ThreeTen-Backport (упомянутый выше.) См.как использовать ThreeTenABP....
на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.
вот пример преобразования текущего системного времени в UTC. Он включает форматирование ZonedDateTime в виде строки, а затем объект String будет проанализирован в объект date с помощью java.текст параметра dateformat.
ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
final DateFormat FORMATTER_YYYYMMDD_HH_MM_SS = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String dateStr = zdt.format(DATETIME_FORMATTER);
Date utcDate = null;
try {
utcDate = FORMATTER_YYYYMMDD_HH_MM_SS.parse(dateStr);
}catch (ParseException ex){
ex.printStackTrace();
}
Если вы используете ThreeTen backport для Android и не может использовать более новую Date.from(Instant instant)
(для чего требуется минимум API 26) Вы можете использовать:
ZonedDateTime zdt = ZonedDateTime.now();
Date date = new Date(zdt.toInstant().toEpochMilli());
или:
Date date = DateTimeUtils.toDate(zdt.toInstant());
пожалуйста, Также прочитайте советы в ответ Базиля Бурка
вы можете сделать это с помощью java.время классы, встроенные в Java 8 и выше.
ZonedDateTime temporal = ...
long epochSecond = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
Date date = new Date(epochSecond * 1000 + nanoOfSecond / 1000000);
Я использую это.
public class TimeTools {
public static Date getTaipeiNowDate() {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Asia/Taipei");
ZonedDateTime dateAndTimeInTai = ZonedDateTime.ofInstant(now, zoneId);
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInTai.toString().substring(0, 19).replace("T", " "));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
потому что
Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
Это не работа!!!
Если вы запустите приложение на своем компьютере, это не проблема. Но если вы работаете в любом регионе AWS или Docker или GCP, это создаст проблему. Потому что компьютер не ваш часовой пояс на облаке. Вы должны правильно установить часовой пояс в коде. Например, Азия / Тайбэй. Затем он будет исправлен в AWS или Docker или GCP.
public class App {
public static void main(String[] args) {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Australia/Sydney");
ZonedDateTime dateAndTimeInLA = ZonedDateTime.ofInstant(now, zoneId);
try {
Date ans = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInLA.toString().substring(0, 19).replace("T", " "));
System.out.println("ans="+ans);
} catch (ParseException e) {
}
Date wrongAns = Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
System.out.println("wrongAns="+wrongAns);
}
}
для приложения docker, как beehuang прокомментировал вы должны установить часовой пояс.
альтернативно вы можете использовать withZoneSameLocal. Например:
2014-07-01T00:00+02:00[GMT+02:00] преобразуется в
Date.from(zonedDateTime.withZoneSameLocal(ZoneId.systemDefault()).toInstant())
to Вт июль 01 00:00: 00 CEST 2014 и
Date.from(zonedDateTime.toInstant())
to Пн 30 июня 22:00: 00 UTC 2014