Вопрос-ответ

Java - Unparseable date

Java - Неразрешимая дата

Я пытаюсь проанализировать дату, но странным образом получаю исключение.

Это код:

import java.util.Date;

String strDate = "Wed, 09 Feb 2011 12:34:27";
Date date;
SimpleDateFormat FORMATTER = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
try {
date = FORMATTER.parse(strDate.trim());
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}

Исключение составляет:


Исключение java.text.ParseException: неразрешимая дата: "Ср., 09 февраля 2011 г. 12:34:27" в java.text.DateFormat.parse(DateFormat.java:337) в DateTest.main(DateTest.java:17)


Я прочитал документацию и думаю, что мой шаблон правильный. Поэтому я не понимаю...

Есть идеи?

Спасибо!

Переведено автоматически
Ответ 1

Вероятно, это из-за того, что язык по умолчанию на вашем компьютере не английский.

Вам следует использовать:

new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);

вместо этого.

Ответ 2

tl; dr

java.util.Date.from (

LocalDateTime.parse(
"Wed, 09 Feb 2011 12:34:27" ,
DateTimeFormatter.ofPattern( "EEE, dd MMM uuuu HH:mm:ss" , Locale.US )
).atZone( ZoneId.of( "America/Montreal" ) )
.toInstant()

)

Подробные сведения

В вопросе и другом ответе используются устаревшие, вызывающие проблемы старые классы даты и времени, которые теперь являются устаревшими, вытесненными классами java.time .

Использование java.time

Во входной строке отсутствуют какие-либо указания часового пояса или смещения от UTC. Поэтому мы анализируем как OffsetDateTime.

Укажите a Locale, чтобы определить (а) человеческий язык для перевода названия дня, названия месяца и тому подобного, и (б) культурные нормы, решающие вопросы аббревиатур, заглавных букв, знаков препинания, разделителей и тому подобного.

String input = "Wed, 09 Feb 2011 12:34:27" ;
Locale l = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE, dd MMM uuuu HH:mm:ss" , l ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

ldt.toString(): 2011-02-09T12:34:27


Часовой пояс

И Вопрос, и другой ответ игнорируют важную проблему часового пояса.

Во входной строке отсутствует часовой пояс или смещение. Мы проанализировали как, LocalDateTime который не является моментом на временной шкале, только смутное представление о возможных моментах. Подобно высказыванию "Рождество начинается в полночь 25 декабря 2017 года", это не имеет смысла, пока вы не разместите его в контексте определенного часового пояса. Рождество в Окленде, Новая Зеландия, наступает намного раньше, чем в Париже, Франция, и еще намного позже в Монреале, Квебек.

Если вы знаете предполагаемый часовой пояс, назначьте ZoneId для получения ZonedDateTime.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ldt.atZone( z ); // Assigning a time zone to determine an actual moment on the timeline.

Преобразование

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

A java.util.Date - это момент на временной шкале по UTC. Итак, нам нужно извлечь Instant из нашего ZonedDateTime. Instant Класс представляет момент на временной шкале в UTC с разрешением в наносекунды (до девяти (9) знаков десятичной дроби).

Instant instant = zdt.toInstant() ;
java.util.Date d = java.util.Date.from( instant ) ; // Convert from java.time to legacy class.

Идем в другом направлении.

Instant instant = d.toInstant() ;  // Convert from legacy class to java.time class.
ZonedDateTime zdt = instant.atZone( z ) ; // Adjust from UTC into a particular time zone.

О java.time

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

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

Чтобы узнать больше, ознакомьтесь с Руководством по Oracle. И найдите в Stack Overflow множество примеров и пояснений. Спецификация - JSR 310.

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

Где получить классы java.time?


  • Java SE 8, Java SE 9, Java SE 10 и более поздние версии

    • Встроенный.

    • Часть стандартного Java API с комплексной реализацией.

    • Java 9 добавляет некоторые незначительные функции и исправления.


  • Java SE 6 и Java SE 7

    • Большая часть функций java.time перенесена обратно на Java 6 и 7 в ThreeTen-Backport.


  • Android

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

Ответ 3

Никогда не используйте SimpleDateFormat или DateTimeFormatter без Locale

Поскольку данная дата и время указаны на английском языке, вы должны использовать Locale.ENGLISH с вашим анализатором даты и времени; в противном случае произойдет сбой синтаксического анализа в системе (компьютере, телефоне и т.д.), которая использует неанглоязычный тип локали.

Также обратите внимание, что API даты и времени java.util и их API форматирования, SimpleDateFormat устарели и подвержены ошибкам. Рекомендуется полностью прекратить их использование и переключиться на современный API для определения даты и времени.

ДЕМОНСТРАЦИЯ:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
public static void main(String[] args) {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
System.out.println(ldt);
}
}

Вывод:

2011-02-09T12:34:27

По умолчанию DateTimeFormatter#ofPattern использует локаль ФОРМАТА по умолчанию, которую JVM устанавливает при запуске в зависимости от среды хоста. То же самое происходит с SimpleDateFormat. Я попытался проиллюстрировать проблему с помощью следующей демонстрации:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
public static void main(String[] args) {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
DateTimeFormatter dtfWithDefaultLocale = null;

System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));

// Setting the JVM's default locale to Locale.FRANCE
Locale.setDefault(Locale.FRANCE);

// Using DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
DateTimeFormatter dtfWithEnglishLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss",
Locale.ENGLISH);
System.out.println("JVM's Locale: " + Locale.getDefault());
System.out.println("DateTimeFormatter's Locale: " + dtfWithEnglishLocale.getLocale());
LocalDateTime zdt = LocalDateTime.parse(strDateTime, dtfWithEnglishLocale);
System.out.println("Parsed with Locale.ENGLISH: " + zdt);

System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + LocalDateTime.parse(strDateTime, dtfWithDefaultLocale));
}
}

Вывод:

JVM's Locale: en_GB
DateTimeFormatter'
s Locale: en_GB
Parsed with JVM's default locale: 2011-02-09T12:34:27
JVM'
s Locale: fr_FR
DateTimeFormatter's Locale: en
Parsed with Locale.ENGLISH: 2011-02-09T12:34:27
JVM'
s Locale: fr_FR
DateTimeFormatter's Locale: fr_FR
Exception in thread "main" java.time.format.DateTimeParseException: Text '
Wed, 09 Feb 2011 12:34:27' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
at Main.main(Main.java:33)

Следующая демонстрация с использованием SimpleDateFormat приведена просто для полноты картины:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
public static void main(String[] args) throws ParseException {
final String strDateTime = "Wed, 09 Feb 2011 12:34:27";
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
System.out.println(date);
}
}

Вывод:

Wed Feb 09 12:34:27 GMT 2011
java