Я получаю следующую ошибку: «java.text.ParseException: Unparseable date: «31 августа 09:53:19 2011»» в этом формате: new SimpleDateFormat("MMM dd HH:mm:ss yyyy");
Кто-нибудь видит проблему?
Я получаю следующую ошибку: «java.text.ParseException: Unparseable date: «31 августа 09:53:19 2011»» в этом формате: new SimpleDateFormat("MMM dd HH:mm:ss yyyy");
Кто-нибудь видит проблему?
Убедитесь, что вы используете правильную локаль. (Конструктор SimpleDateFormat(String)
использует язык системы по умолчанию, который может отличаться от того, который вы хотите использовать.)
Это отлично работает на моей машине:
String input = "Aug 31 09:53:19 2011";
DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
System.out.println(df.parseObject(input));
(Например, при использовании Locale.FRENCH
получается ParseException
.)
Сам формат подходит для ввода, который вы дали. Но вы можете получить эту ошибку, если ваш языковой стандарт по умолчанию установлен на что-то, где «Авг» не является допустимым сокращением названия месяца. Попробуйте использовать, например, Locale.US
, и вы увидите, что это сработает:
DateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.US);
Date date = df.parse("Aug 31 09:53:19 2011");
2017-08-01T08:32:38.5544401-05:00
, и это шаблон yyyy-MM-dd'T'HH:mm:ssz
. и я получаю исключение. Пожалуйста помоги
- person eC Droid; 01.08.2017
SimpleDateFormat
не может работать с 7 цифрами долей секунды. См.: stackoverflow.com/questions/12000673/
- person Jesper; 01.08.2017
String actualFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSz";
и вот результат Orignal Date: 2017-08-01T08:50:36.8762641-05:00 Converted Time: 18:50:36
Это правильно?
- person eC Droid; 01.08.2017
08:50:36.8762641
эта цифра 36,8762641?
- person eC Droid; 02.08.2017
yyyy-MM-dd'T'HH:mm:ss
- person eC Droid; 02.08.2017
Locale
strong>, чтобы определить человеческий язык и культурные нормы, используемые при переводе названия месяца.Надуманный пример:
LocalDateTime.parse( // Parse input text as a `LocalDateTime` lacking any concept of time zone or offset-from-UTC.
"Aug 31 09:53:19 2011" ,
DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss yyyy" ) // Specify formatting pattern to match input string.
.withLocale( Locale.US ) // The `Locale` determines the human language and cultural norms used in translating the input text.
) // Returns a `LocalDateTime` object.
Два других ответа от aioobe и by Jesper верны: неявное использование Locale
с человеческим языком, который не соответствует языку введенного вами текста.
Этот ответ объясняет новый способ выполнения работы. Кроме того, другие ответы не затрагивают важнейшую проблему часового пояса.
Перенесемся через несколько лет после этой публикации, и теперь у нас есть новый пакет java.time, встроенный в Java 8 и более поздние версии. Эти новые классы заменяют старые классы java.util.Date/.Calendar и SimpleDateFormat. Эти старые классы оказались проблемными, запутанными и ошибочными.
Определите данные для анализа и их формат.
String input = "Aug 31 09:53:19 2011";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd HH:mm:ss uuuu" );
Если не указано, DateTimeFormatter
назначается Locale
, который в настоящее время используется по умолчанию в JVM. Это значение по умолчанию может измениться в любой момент, даже во время выполнения (!). Поэтому всегда указывайте желаемое/ожидаемое Locale
.
formatter = formatter.withLocale( Locale.US ); // Or Locale.UK, Locale.CANADA_FRENCH, etc.
Учитывая, что во входных данных отсутствует какая-либо информация о часовом поясе или смещении от-UTC, следует анализировать как LocalDateTime
.
LocalDateTime ldt = LocalDateTime.parse( input , formatter );
Если из контекста вы знаете предполагаемое смещение от UTC или часовой пояс для этого значения даты и времени, назначьте его.
Если в формате UTC, используйте константу ZoneOffset.UTC
, чтобы получить объект OffsetDateTime
.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Часовой пояс — это смещение относительно UTC плюс набор правил для обработки аномалий, таких как переход на летнее время (DST). Используйте правильные названия часовых поясов, а не аббревиатуры из 3-4 букв.
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId_Montreal );
Этот элемент человеческого языка был ключевым недостающим элементом для ответа на Вопрос. Указание правильного Locale
для человеческого языка, соответствующего языку вашей входной строки, решает эту проблему.
Но обратите внимание, что часовой пояс также имеет решающее значение; другие ответы игнорировали эту проблему, тем самым неявно используя текущий часовой пояс JVM по умолчанию. Это не рекомендуется, так как это зависит от операционной системы хоста в качестве начального значения по умолчанию (поэтому может варьироваться), и, кроме того, любой код в любом потоке любого приложения в JVM может изменить текущий часовой пояс JVM по умолчанию во время em> время выполнения. Лучше указать желаемый/ожидаемый часовой пояс, чем неявно полагаться на значение по умолчанию.
Обратите внимание на синтаксис. Эти классы должны быть неизменяемыми. Таким образом, вместо модификации (мутации) объекта новый новый объект создается на основе значений старого объекта. Это означает, что мы не затрагиваем DateTimeFormatter
объект, определенный выше и хранящийся в переменной formatter
(ссылка на объект). Мы создаем, используем и отбрасываем новый объект DateTimeFormatter (на самом деле, два новых объекта) в этой строке кода.
В документации предлагается альтернативный способ разбора строки — вызвать метод parse
, в котором вы передаете ссылка на метод (новое в Java 8) из класса желаемого результата (как TemporalQuery
): ZonedDateTime::from
, LocalDateTime::from
, LocalDate::from
и т. д.
ZonedDateTime zdt = formatter.withZone( zoneId_Montreal ).withLocale( Locale.ENGLISH ).parse( input, ZonedDateTime :: from );
Для демонстрации давайте развернёмся и создадим строковое представление этого значения ZonedDateTime
, но на французском языке Квебека.
String output = formatter.withLocale( Locale.CANADA_FRENCH ).format( zdt );
Еще лучше, давайте локализовать, а не жестко кодировать определенный формат.
String outputLocalized = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ).format( zdt );
Дамп на консоль.
System.out.println( "input: " + input );
System.out.println( "formatter: " + formatter );
System.out.println( "zdt: " + zdt );
System.out.println( "output: " + output );
System.out.println( "outputLocalized: " + outputLocalized );
Когда бег.
input: Aug 31 09:53:19 2011
formatter: Text(MonthOfYear,SHORT)' 'Value(DayOfMonth,2)' 'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)' 'Value(YearOfEra,4,19,EXCEEDS_PAD)
zdt: 2011-08-31T09:53:19-04:00[America/Montreal]
output: août 31 09:53:19 2011
outputLocalized: mercredi 31 août 2011 9 h 53 EDT
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?
Locale
, так и часовой пояс в вашей работе с датой и временем, а не неявно полагайтесь на текущее значение по умолчанию JVM. Оба могут измениться в любой момент во время выполнения. - person Basil Bourque   schedule 18.03.2016java.util.Date
,java.util.Calendar
иjava.text.SimpleDateFormat
теперь являются устаревшими, вытесненными java.time, встроенные в Java 8 и более поздние версии. См. учебник от Oracle. - person Basil Bourque   schedule 27.04.2018