Как конвертировать 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

на 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);

Если вас интересует только сейчас, просто используйте:

Date d = new Date();

Я использую это.

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