代码之家  ›  专栏  ›  技术社区  ›  James McMahon

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

  •  4
  • James McMahon  · 技术社区  · 14 年前

    我在用 java.text.SimpleDateFormat 分析XML文档中日期/时间值的字符串表示形式。我看到的所有时间都是12小时值被12小时移动到未来,也就是说,中午20分钟被解析为第二天午夜20分钟。

    我编写了一个单元测试,它似乎可以确认分析时出错(我检查了 getTime() 使用linux shell命令 date )现在我想知道:

    • 里面有虫子吗 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();
            }
        }
    }
    
    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分钟的(错误)时间。

    4 回复  |  直到 14 年前
        1
  •  3
  •   bobince    14 年前

    这个 K 中的说明符 SimpleDateFormat documented 从0开始使用小时。不知道如果你要求它分析一个超出范围的值,比如12,会发生什么…它可能是你输入的 00:20 PM 然后再加上12个小时。

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

    为什么破碎的12小时制的恐怖不会消失?

        2
  •  3
  •   muddybruin    14 年前

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

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

        3
  •  1
  •   OscarRyz    14 年前

    如果你用K……等等…(阅读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
  •  0
  •   hansaplast    14 年前

    作为旁注:我强烈建议切换到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 )