2009-08-21 3 views
10

Я действительно почесываю голову на этом. Я использовал 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. Какого черта? - он даже не разобрался в неправильную дату все время!


Update: Это установило это красиво. Разве вы не знали бы это, это было неправильно использовано в нескольких других местах. Должен любить отладку кода других людей :)

+3

Я бы хотел, чтобы люди переставали называть вещи «причудливыми» и «странными» всякий раз, когда они совершали ошибки. :/ – Bombe

+0

Извините. Я отлаживал код, который кто-то много лет написал моему старшему, и я ожидал, что смогу доверять. –

ответ

25

Я думаю, что вы хотите использовать формат 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()); 

Если распечатать

Ср авг 19 12:00:00 EDT 2009

2

Вы печатаете представление 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)); 
+0

Я попробую, но я не думаю, что это решит проблему. В моем приложении я фактически не конвертирую обратно в строку. Я сохраняю дату в базе данных, и там тоже неправильно. –

+0

Являются ли ваши строки строк согласованными? Некоторые СУБД автоматически преобразуют значения, если они могут понять, что происходит, а некоторые - нет. Являются ли проблемные значения в столбце (столбцах) с различным форматированием, применяемым на уровне db? Или из соединения, которое имеет разные параметры? – DaveE

1

ТЛ; Др

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, теперь в maintenance mode, советует перейти на java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений.

Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport и дополнительно выполнен с возможностью Android в ThreeTenABP (см How to use…).

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