Dateformatter в java [дубликат]
На этот вопрос уже есть ответ здесь:
Я использую приведенный ниже код для форматирования строк даты разрешения миллисекунды. Он работает для 2018-09-14T13:05:21.329Z, но не для 2018-09-14T13:05:21.3Z. Может ли кто-нибудь подсказать причину и как ее исправить?
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
SimpleDateFormat sdfDestination = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date parsedDate = formatter.parse(date);
String destDate = sdfDestination.format(parsedDate);
return destDate;
} catch (java.text.ParseException parseException) {
logger.error("Parse Exception occured while converting publication time to date "
+ "format 'yyyy-MM-dd HH:mm:ss'", parseException);
}
Я получаю ниже исключение:
java.text.ParseException: Unparseable date: "2018-09-14T13:05:21.3Z"
at java.text.DateFormat.parse(Unknown Source) ~[na:1.8.0_181]
at com.noordpool.api.implementation.utility.Utility.parseDate(Utility.java:136) [classes/:na]
at com.noordpool.api.implementation.utility.Utility.parseMessage(Utility.java:77) [classes/:na]
4 ответов:
Ваша единственная проблема заключается в том, что вы используете неправильный шаблон для
SimpleDateFormat, вам нужно изменить:DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");Кому:
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");Потому что
Z, используемый в строкеdate, означает "смещение нулевого часа", поэтому вам просто нужно передать его как'Z'в вашем шаблоне.Это рабочая демонстрация с правильным рисунком.
Редактировать:
И чтобы заставить вещи работать с различными локалями и часовыми поясами, вам нужно использовать соответствующие
LocaleКогда вы создаете экземплярSimpleDateFormat, Вот каким должен быть код:DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
Единственная возможная проблема, которую я вижу, заключается в том, что вы неправильно передаете миллисекунды, и программа не знает, что с этим делать.
Таким образом, последняя часть форматера указывает с миллисекундами и часовым поясом как .SSSX
Но как он оценивает 3Z для входа в это? Я имею в виду, вы говорите, что это 300 часовой пояс Z, или говорите, что это 003 часовой пояс Z, или еще хуже, попробуйте разобрать его как 3Z, что, надеюсь, вы видите, что вы не можете превратить " 3Z " в число.
Чтобы исправить это, Я бы проверил ваш ввод "дата" и убедился, что часть миллисекунд всегда состоит из 3 цифр, это устраняет двусмысленность, и программа всегда знает, что вы имеете в виду "300 миллисекунд, часовой пояс Z".
Существует проблема в java 8, где количество символов, которые вы указали с помощью форматера, должно точно совпадать (что не указано в документации). Вы можете использовать три различных Формататора и использовать вложенное исключение следующим образом:
DateFormat format1 = new SimpleDateFormat("y-M-d'T'H:m:s.SX"); DateFormat format2 = new SimpleDateFormat("y-M-d'T'H:m:s.SSX"); DateFormat format3 = new SimpleDateFormat("y-M-d'T'H:m:s.SSSX"); Date parsedDate; try { // Parsing for the case - 2018-09-14T13:05:21.3Z parsedDate = format1.parse(date); } catch (ParseException e1) { try { // Parsing for the case - 2018-09-14T13:05:21.32Z parsedDate = format2.parse(date); } catch (ParseException e2) { try { // Parsing for the case - 2018-09-14T13:05:21.329Z parsedDate = format3.parse(date); } catch (ParseException e2) { //The input date format is wrong logger.error("Wrong format for date - " + date); } } }
[12]}Java.время
DateTimeFormatter dtfDestination = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"); String date = "2018-09-14T13:05:21.3Z"; String destDate = Instant.parse(date) .atZone(ZoneId.of("Indian/Comoro")) .format(dtfDestination); System.out.println(destDate);Выходные данные этого фрагмента:
2018-09-14 16:05:21
Пожалуйста, замените правильный часовой пояс, если он не был индийским / Comoro, так как правильный вывод зависит от использования правильного часового пояса. Если вы хотите использовать часовой пояс вашего JVM по умолчанию, укажите
ZoneId.systemDefault(), но имейте в виду, что значение по умолчанию может быть изменено в любое время из других частей вашей программы или других программ, работающих в том же JVM.Я эксплуатирую дело в том, что ваша строка,
"2018-09-14T13:05:21.3Z", находится в формате ISO 8601, формате, который используют классы java.time parse по умолчанию, то есть без явного форматирования.Instant.parseпринимает что-либо от 0 до 9 десятичных знаков на секундах, так что нет никаких проблем, давая ему строку только с 1 десятичной, как вы сделали. В сравнении с этим нет способа, которым старомодныйSimpleDateFormatможет разобрать 1 десятичный знак на секундах с полной точностью, так как он принимает букву шаблона (верхний регистр)S, чтобы означать миллисекунды, так что.3будет проанализировано как 3 миллисекунды, а не 3 десятых секунды, как это означает.Jahnavi Paliwal уже правильно поставил диагноз и объяснил причину полученного вами исключения.
Классы даты и времени, которые вы использовали,
DateFormat,SimpleDateFormatиDate, все они давно устарели иSimpleDateFormatв особенности печально известны. Поскольку вы, кажется, используете Java 8 (и даже если вы этого не сделали), я предлагаю вам полностью избегать этих классов и использовать java.время вместо.Ссылки
- Oracle tutorial: Date Time объяснение того, как использовать
java.time.- статья в Википедии: ISO 8601
Comments