it-swarm.com.ru

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. Формат даты выше является стандартным Дата?

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

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

58
Ironluca

Для преобразования Instant в ZonedDateTime, ZonedDateTime предлагает метод ZonedDateTime.ofInstant(Instant, ZoneId) . Так

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

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

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

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

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

32
assylias

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

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

enter image description here

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

Помещение

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

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 31 .

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

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

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

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

1
Basil Bourque

Ответ не сработал для меня в Java 10 хранилище util.Date в 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)
0
TheArchitect