Несогласованный синтаксический анализ даты с использованием SimpleDateFormat
Я действительно почесываю голову над этим. Я использовал SimpleDateFormat
без каких-либо проблем некоторое время, но теперь использование SimpleDateFormat для синтаксического анализа дат (иногда) просто неверно.
В частности:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = sdf.parse("2009-08-19 12:00:00");
System.out.print(date.toString());
печатает строку Wed Aug 19 00:00:00 EDT 2009
. Какого черта? - он даже не анализируется в неправильную дату все время!
Обновление:. Это исправило это красиво. Разве вы не знали бы это, это было неправильно использовано в нескольких других местах. Должен любить отладку кода других людей:)
Ответы
Ответ 1
Я думаю, вы хотите использовать формат HH
, а не "hh", чтобы вы использовали часы между 00-23. 'hh' принимает формат с 12-часовым шагом, поэтому он предполагает, что он находится в AM.
Итак, это
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2009-08-19 12:00:00");
System.out.print(date.toString());
Должен распечатываться
Wed Aug 19 12:00:00 EDT 2009
Ответ 2
Час должен быть указан как HH вместо hh. Ознакомьтесь с разделом "Модели даты и времени" в http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html
Ответ 3
Вы печатаете представление toString() даты, а не представление формата. Вы также можете проверить представление часов. H и h означают что-то другое. H - для 24-часового такта (0-23), h - для 12-часового такта (1-12), (также есть k и K для 1-24 и 0-11 соответственно)
Вам нужно сделать что-то вроде:
//in reality obtain the date from elsewhere, e.g. new Date()
Date date = sdf.parse("2009-08-19 12:00:00");
//this format uses 12 hours for time
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//this format uses 24 hours for time
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.print(sdf.format(date));
System.out.print(sdf2.format(date));
Ответ 4
TL;DR
LocalDateTime ldt = LocalDateTime.parse( "2009-08-19 12:00:00".replace( " " , "T" ) );
java.time
Другие ответы правильные, но используйте устаревшие классы времени. Эти трудные старые классы были вытеснены классами java.time.
Ваша строка ввода близка к стандарту ISO 8601. Подстройте, заменив SPACE посередине на T
. Затем он может быть проанализирован без указания шаблона форматирования. Классы java.time используют ISO 8601 по умолчанию при разборе/генерации строк.
String input = "2009-08-19 12:00:00".replace( " " , "T" );
Входные данные не имеют информации о offset-from-UTC или часовом поясе. Поэтому мы анализируем как LocalDateTime
.
LocalDateTime ldt = LocalDateTime.parse( input );
Если по контексту вы знаете предполагаемое смещение, примените его. Возможно, он предназначался для UTC (смещение нуля), где мы можем использовать константу ZoneOffset.UTC
.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Или, может быть, вы знаете, что он предназначен для определенного часового пояса. Часовой пояс - это смещение плюс набор правил для обработки аномалий, таких как переход на летнее время (DST).
ZonedDateTime zdt = ldt.atZone( ZoneId.of( "America/Montreal" ) );
О java.time
Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют старые неудобные классы времени, такие как java.util.Date
, .Calendar
и java.text.SimpleDateFormat
.
Проект Joda-Time, теперь режим обслуживания, советует перейти на java.time.
Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений.
Большая часть функциональных возможностей java.time возвращается на Java 6 и 7 в ThreeTen-Backport и далее адаптируется к Android в ThreeTenABP (см. Как использовать...).
Проект ThreeTen-Extra расширяет java.time с помощью дополнительных классов. Этот проект является доказательством возможных будущих дополнений к java.time.