Java8 java.util.Date преобразование в java.time.ZonedDateTime

Я получаю следующее исключение при попытке конвертировать java.util.Date в java.time.LocalDate,

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type java.time.Instant

Код выглядит следующим образом:

public static Date getNearestQuarterStartDate(Date calculateFromDate){

    int[] quaterStartMonths={1,4,7,10};     
    Date startDate=null;

    ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
    int frmDateMonth=d.getMonth().getValue();

Что-то не так в том, как я использую ZonedDateTime учебный класс?

Согласно документации, это должно преобразовать java.util.Date Возражать ZonedDateTime, Формат даты выше является стандартным Дата?

Должен ли я отступить на время Йода?

Если бы кто-то мог дать какое-то предложение, было бы здорово.

2 ответа

Решение

Чтобы преобразовать Instant к ZonedDateTime, ZonedDateTime предлагает метод ZonedDateTime.ofInstant(Instant, ZoneId), Так

Итак, если вы хотите ZonedDateTime в часовом поясе по умолчанию ваш код должен быть

ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());

Чтобы получить ZonedDateTime из даты, вы можете использовать:

calculateFromDate.toInstant().atZone(ZoneId.systemDefault())

Вы можете позвонить toLocalDate метод, если вам нужен LocalDate. Смотрите также: Преобразование java.util.Date в java.time.LocalDate.

Ответ assylias и Ответ JB Nizet оба являются правильными:

  1. Вызовите новый метод преобразования, добавленный в унаследованный класс, java.util.Date::toInstant,
  2. Вызов Instant::atZone, передавая ZoneId, в результате чего ZonedDateTime,

Но ваш пример кода нацелен на четверти. Для этого читайте дальше.

помещение

Нет необходимости самостоятельно обрабатывать помещения. Используйте класс, уже написанный и протестированный.

org.threeten.extra.YearQuarter

Классы java.time расширены проектом ThreeTen-Extra. Среди множества удобных классов, представленных в этой библиотеке, вы найдете Quarter а также YearQuarter,

Сначала получите свой ZonedDateTime,

ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;

Определите квартал года для этой конкретной даты.

YearQuarter yq = YearQuarter.from( zdt ) ;

Далее нам нужна дата начала этого квартала.

LocalDate quarterStart = yq.atDay( 1 ) ;

Хотя я не обязательно рекомендую это делать, вы можете использовать одну строку кода, а не реализовывать метод.

LocalDate quarterStart =                    // Represent a date-only, without time-of-day and without time zone.
    YearQuarter                             // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`. 
    .from(                                  // Given a moment, determine its year-quarter.
        myJavaUtilDate                      // Terrible legacy class `java.util.Date` represents a moment in UTC as a count of milliseconds since the epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
        .toInstant()                        // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the epoch of 1970-01-01T00:00:00Z. 
        .atZone(                            // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
            ZoneID.of( "Africa/Tunis" )     // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`. 
        )                                   // Returns a `ZonedDateTime` object.
    )                                       // Returns a `YearQuarter` object.
    .atDay( 1 )                             // Returns a `LocalDate` object, the first day of the quarter. 
;

Кстати, если вы можете отказаться от использования java.util.Date в общем, сделай так. Это ужасный класс, вместе с его братьями и сестрами, такими как Calendar, использование Date только там, где это необходимо, когда вы взаимодействуете со старым кодом, который еще не обновлен до java.time.


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date, Calendar & SimpleDateFormat,

Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310.

Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классы.

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval, YearWeek, YearQuarter и многое другое.

Ответ не сработал для меня на Java 10 для хранения util.ate в UTC.

Date.toInstant(), по-видимому, конвертирует EpochMillis в местный часовой пояс сервера.

ZDT.ofInstant (instant, zoneId) и instant.atZone(zoneId), кажется, просто помечают TZ в данный момент, но он уже перепутан с.

Я не смог найти способ предотвратить связывание Date.toInstant() с временем UTC с системным часовым поясом.

Единственный способ обойти это - пройти через класс sql.Timestamp:

new java.sql.Timestamp(date.getTime()).toLocalDateTime()
                                      .atZone(ZoneId.of("UTC"))
                                      .withZoneSameInstant(desiredTZ)
Другие вопросы по тегам