Java 为什么下午12:20解析为第二天的0:20?

Java 为什么下午12:20解析为第二天的0:20?,java,parsing,date,Java,Parsing,Date,我正在使用java.text.simpleDataFormat解析XML文档中日期/时间值的字符串表示形式。我看到所有时间的小时值都是12,在未来的12个小时内,我。E午后20分钟被解析为第二天午夜后20分钟 我编写了一个单元测试,它似乎确认了错误是在解析时发生的(我使用linux shell命令date检查了getTime()中的返回值)。现在我想知道: parse()方法中是否存在错误 输入字符串是否有问题 输入的格式字符串是否错误 输入数据取自雅虎的YWeather服务。以下是测试及其

我正在使用
java.text.simpleDataFormat
解析XML文档中日期/时间值的字符串表示形式。我看到所有时间的小时值都是12,在未来的12个小时内,我。E午后20分钟被解析为第二天午夜后20分钟

我编写了一个单元测试,它似乎确认了错误是在解析时发生的(我使用linux shell命令
date
检查了
getTime()
中的返回值)。现在我想知道:

  • parse()
    方法中是否存在错误
  • 输入字符串是否有问题
  • 输入的格式字符串是否错误
输入数据取自雅虎的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();
        }
    }
}
2010年4月8日星期四下午12:20 CEST 2010年4月9日星期五上午0:20 CEST 2010年4月8日星期四上午12:20 CEST 2010年4月8日星期四下午0:20 CEST
第二次迭代的第二个输出行有点奇怪,因为00:20不是PM。但是,
Date
对象的毫秒值对应于中午后20分钟的(错误)时间。

如果在格式字符串中使用K,它的值从0到11(因此12:20实际上应该是00:20)。 你可以试着用h代替,从1到12,这是你所期望的


SimpleDateFormat
中的
K
说明符使用从0开始的小时数。不确定如果你要求它解析一个超出范围的值,比如12,会发生什么。。。这可能就好像你输入了
00:20 PM
,然后额外增加了12个小时

如果要在第一个小时使用12,请尝试使用
h
说明符


为什么坏掉的12小时时钟系统的恐怖还没有消失呢?

如果你用K。。。。等等等等。。。(阅读博宾斯的回答)

要强制执行预期行为(并在使用12时引发解析异常),请将解析器的lenient属性设置为false:

....
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)

作为旁注:我强烈建议改用Joda Time

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 Time似乎还不支持时区解析(请参见)

是的,为什么它不支持呢?不管怎样,这很有帮助。谢谢。你的答案基本上和博宾斯的一样,但他的(非常)精确一点,所以我接受了这个答案,并投了你的一票。希望没问题。这是“选择未损坏”的另一个很好的例子。尽管我从未在成熟且广泛使用的标准库中遇到过bug,但如果我找不到问题,我有时还是会指责库。到目前为止,我一直被证明是错的。
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));