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 оба являются правильными:
- Вызовите новый метод преобразования, добавленный в унаследованный класс,
java.util.Date::toInstant
, - Вызов
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?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11 и более поздние версии - часть стандартного API Java со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
- Android
- Более поздние версии Android связывают реализации классов java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект 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)