【问题标题】:Why does 12:20 PM parse to 0:20 on the next day?为什么 12:20 PM 解析为第二天的 0:20?
【发布时间】:2010-04-08 20:20:17
【问题描述】:

我正在使用java.text.SimpleDateFormat 来解析 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 PM CEST 2010 年 4 月 9 日星期五 0:20 AM CEST 2010 年 4 月 8 日星期四 12:20 AM CEST 2010 年 4 月 8 日星期四 0:20 PM CEST

第二次迭代的第二行输出有点奇怪,因为 00:20 不是 PM。但是,Date 对象的毫秒值对应于中午过去 20 分钟的(错误)时间。

【问题讨论】:

  • 这是另一个很好的“SELECT 没有损坏”的例子。即使我从来没有遇到过成熟且广泛使用的标准库中的错误,但如果我找不到问题,我有时仍然会指责该库。到目前为止,我一直被证明是错误的。

标签: java parsing date


【解决方案1】:

SimpleDateFormat 中的 K 说明符是 documented 以使用从 0 开始的小时数。不确定如果您要求它解析像 12 这样的超出范围的值会发生什么......它可能正在起作用就好像你输入00:20 PM,然后再增加12小时。

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

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

【讨论】:

  • 是的,为什么不呢?无论如何,这有帮助。
【解决方案2】:

如果你在格式字符串中使用 K,它的范围是 0-11(所以 12:20 应该是 00:20)。 您可以尝试使用 h 代替,从 1 到 12,这是您所期望的。

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

【讨论】:

  • 谢谢。您的答案与 bobince 的答案基本相同,但他的答案(非常)稍微准确一些,所以我接受了这个答案并赞成您的答案。希望没关系。
【解决方案3】:

如果你使用 K .... etc. etc. ...(阅读 bobince 的回答)

要强制执行预期的行为(并在使用 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)

【讨论】:

    【解决方案4】:

    作为一个侧面标记​​:我强烈建议切换到 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 似乎还不支持解析时区(见http://joda-time.sourceforge.net/api-release/org/joda/time/format/DateTimeFormat.html

    【讨论】:

      猜你喜欢
      • 2015-07-30
      • 2022-11-20
      • 2022-01-05
      • 1970-01-01
      • 2015-11-14
      • 2017-10-17
      • 1970-01-01
      • 2013-09-03
      相关资源
      最近更新 更多