Я разбирал даты в форматах ниже. Я поддерживаю массив этих форматов и анализирую каждую строку даты во всех этих форматах.
Код, который я использовал, был -
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
simpleDateFormat.setTimeZone(timeZone); //timeZone is a java.util.TimeZone object
Date date = simpleDateFormat.parse(dateString);
Теперь я хочу также проанализировать формат yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX, но при использовании SimpleDateFormat 6-значные микросекунды не учитываются. Итак, я заглянул в пакет java.time.
Для разбора форматов yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX мне понадобится класс OffsetDateTime, а для других форматов мне понадобится класс ZonedDateTime. Формат будет установлен в классе DateTimeFormatter.
Есть ли способ использовать один класс, например SimpleDateFormat, для передачи всех форматов?
Это зависит от того, какой результат вам нужен. Если вам подходит что-то вроде Date (то есть без часового пояса или смещения), просто используйте Instant и yourDateTimeFormatter.parse(yourString, Instant::from).
Что выявил ваш поиск? Уже есть пара довольно похожих вопросов.
К тому же «любой формат» явно невозможен. Не могли бы вы уточнить свои требования к формату? Может привести 5 примеров?
@ OleV.V. Я устанавливаю часовой пояс с помощью setTimeZone, но формат yyyy-MM-dd'T'HH: mm: ss.SSSSSSXXX уже имеет часовой пояс в этом формате. Если я использую ZonedDateTime, используется часовой пояс, указанный с помощью withZone (), а не часовой пояс в строке даты. Если я использую OffsetDateTime, другие форматы не могут быть проанализированы.
Угу? «Если зона была проанализирована непосредственно из текста,…, то эта зона переопределения (то есть зона из withZone()) не действует». (из withZone документация)
Связанный: SimpleDateFormat игнорировать символы. Взгляните и поищите больше.
@ OleV.V. Когда текст имеет Z в конце и withZone () устанавливает часовой пояс на IST, withZone действует.
Это может быть потому, что Z - это смещение, а не часовой пояс. java.time отличает. Вам нужно смещение (Z) от строки?
@ OleV.V. rextester.com/LNT50546. Если вы отметите это, время будет 02:17 UTC, но оно отображается как 02:17 IST, потому что используется withZone ().
Это действительно досадно и неправильно. На моем Java 11 я получил 2018-10-22T07:47:58.717853+05:30[Asia/Calcutta], и это правильный момент времени. И если вместо этого я использую OffsetDateTime.parse(date, istFormat), я получаю 2018-10-22T02:17:58.717853Z, то есть смещение от строки, а не от форматтера.
@ OleV.V. Я использую Java 8




Поскольку ваша Java 8 ведет себя не так, как можно было бы ожидать, я предлагаю обходным путем попытаться сначала выполнить синтаксический анализ без зоны. Если зона или смещение извлекаются из строки, это будет использоваться. Если парсинг без зоны не удается, попробуйте с зоной. Это делает следующий метод:
private static void parseAndPrint(String formatPattern, String dateTimeString) {
// Try parsing without zone first
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
Instant parsedInstant;
try {
parsedInstant = formatter.parse(dateTimeString, Instant::from);
} catch (DateTimeParseException dtpe) {
// Try parsing with zone
ZoneId defaultZone = ZoneId.of("Asia/Calcutta");
formatter = formatter.withZone(defaultZone);
parsedInstant = formatter.parse(dateTimeString, Instant::from);
}
System.out.println("Parsed instant: " + parsedInstant);
}
Давай попробуем:
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", "2018-10-22T02:17:58.717853Z");
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", "2018-10-22T02:17:58.717853");
parseAndPrint("EEE MMM d HH:mm:ss zzz yyyy", "Mon Oct 22 02:17:58 CEST 2018");
Вывод на Java 8:
Parsed instant: 2018-10-22T02:17:58.717853Z Parsed instant: 2018-10-21T20:47:58.717853Z Parsed instant: 2018-10-22T00:17:58Z
Первый пример имеет смещение в строке, а последний - аббревиатуру часового пояса в строке, и в обоих случаях они соблюдаются: моментальная печать скорректировала время в UTC (поскольку Instant всегда печатает в UTC, его метод toString делает Конечно). В среднем примере в строке нет ни смещения, ни часового пояса, поэтому используется часовой пояс по умолчанию для Азии / Калькутты, указанный в методе.
Тем не менее, анализ трех- или четырехбуквенной аббревиатуры часового пояса, такой как CEST, является опасной и обескураживающей практикой, поскольку сокращения часто неоднозначны. Я включил пример только для демонстрации.
Is there a way to use a single class…?
Я использовал Instant для всех случаев, так что да, есть способ использовать только один класс. Ограничение состоит в том, что впоследствии вы не знаете, был ли в строке какой-либо часовой пояс или смещение и что это было. Вы тоже не знали, когда использовали SimpleDateFormat и Date, поэтому я решил, что все в порядке?
Ошибка в Java 8?
Результаты ваша демонстрация на тестере REX разочаровывают и ошибочны и не согласуются с результатами, которые я получил на Java 11. Мне кажется, что вы столкнулись с ошибкой в Java 8, возможно, этот: синтаксический анализ с DateTimeFormatter.withZone не ведет себя так, как описано в javadocs.
Я использовал OffsetDateTime для этого конкретного формата. Спасибо за помощь.
Возможный дубликат Преобразование строки Java в дату, отметьте этот ответ stackoverflow.com/a/4216767/4892907