2010-04-08 3 views
4

Я использую java.text.SimpleDateFormat для анализа строковых представлений значений даты/времени внутри XML-документа. Я вижу все времена, которые имеют значение часа 12, сдвинутое на 12 часов в будущее, т.е. е. Через 20 минут после полудня анализируется 20 минут за полночь следующего дня.Почему 12:20 разводят до 0:20 на следующий день?

Я написал блок-тест, который, как представляется, подтверждает, что ошибка возникает при разборе (я проверил возвращаемые значения от getTime() с помощью команды оболочки Linux date). Теперь мне интересно:

  • есть ошибка в методе parse()?
  • есть что-то не так с входной строкой?
  • Я использую неправильную строку формата для ввода?

Данные ввода взяты из службы Yahoo YWeather. Вот тест и его выход:

public class YWeatherReaderTest 
{ 
    public static final String[] rgDateSamples = { 
     "Thu, 08 Apr 2010 12:20 PM CEST", 
     "Thu, 08 Apr 2010 12:20 AM CEST" 
    }; 

    public void dateParsing() throws ParseException 
    { 
     DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy K:m a z", 
                Locale.US); 
     for (String dtsSrc : YWeatherReaderTest.rgDateSamples) { 
      Date dt = formatter.parse(dtsSrc); 
      String dtsDst = formatter.format(dt); 
      System.out.println(dtsSrc); 
      System.out.println(dtsDst); 
      System.out.println(); 
     } 
    } 
} 
 
Thu, 08 Apr 2010 12:20 PM CEST 
Fri, 09 Apr 2010 0:20 AM CEST 

Thu, 08 Apr 2010 12:20 AM CEST 
Thu, 08 Apr 2010 0:20 PM CEST 

Второй линейный выход второй итерации немного странно, потому что 00:20 не PM. Однако значение миллисекунды объекта Date соответствует (ошибочному) времени в течение 20 минут после полудня.

+0

Это еще один хороший пример «SELECT ISN» t сломан ". Несмотря на то, что я никогда не встречал ошибку в зрелой и широко используемой стандартной библиотеке, я все же иногда обвиняю библиотеку, если не могу найти проблему. И до сих пор я всегда ошибался. –

ответ

3

K спецификатор SimpleDateFormat является documented использовать часы, начиная с 0. Не уверен, что должно произойти, если вы попросите его разобрать значение вне диапазона, как 12 ... это, вероятно, действует как если бы вы ввели 00:20 PM, а затем добавили дополнительные 12 часов.

Если вы хотите использовать 12 в течение первого часа, попробуйте использовать спецификатор h.

Почему бы не угасить ужас разбитой 12-часовой системы часов?

+0

Да, почему? Во всяком случае, это помогло. –

3

Если вы используете K в строке формата, оно идет от 0-11 (так что 12:20 действительно должно быть 00:20). Вы можете попробовать использовать h вместо этого, который идет от 1-12, чего вы ожидали.

http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html

+0

Спасибо. Ваш ответ по существу тот же, что и у bobince, но его (очень) немного более точно, поэтому я принял это и поддержал ваше. Надеюсь, все в порядке. –

1

Если вы используете K .... и т.д. и т.п. ... (читать ответ bobince в)

Чтобы заставить ожидаемое поведение (и бросить исключение синтаксического анализа при использовании 12) установить щадящее свойство парсера к ложному :

.... 
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy K:m a z", 
               Locale.US); 
formatter.setLenient(false); 
for (String dtsSrc : YWeatherReaderTest.rgDateSamples) { 
.... 

Выход:

java YWeatherReaderTest 
Exception in thread "main" java.text.ParseException: Unparseable date: "Thu, 08 Apr 2010 12:20 PM CEST" 
at java.text.DateFormat.parse(DateFormat.java:335) 
at YWeatherReaderTest.dateParsing(YWeatherReaderTest.java:17) 
at YWeatherReaderTest.main(YWeatherReaderTest.java:25) 
+0

Это полезно знать. –

0

в качестве побочного знака: я настоятельно рекомендую, чтобы перейти к Joda времени.

Функции java.util.date имеют тенденцию просто гадать (что в вашем случае было не тем, что вы ожидали). Joda Time выдает исключение, если оно не соответствует спецификациям.

Это близко к тому, что у вас есть:

String s = "Thu, 08 Apr 2010 12:20 PM"; 
String format = "EEE, dd MMM yyyy h:m a"; 
DateTimeFormatter fmt = DateTimeFormat.forPattern(format).withLocale(Locale.US); 
System.out.println(fmt.parseDateTime(s)); 

Хотя Joda время, кажется, еще не поддерживает синтаксический анализ временной зоны (см http://joda-time.sourceforge.net/api-release/org/joda/time/format/DateTimeFormat.html)