9

我一直在尝试隔离我的应用程序中的错误。我成功地产生了以下“谜语”:

SimpleDateFormat f1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date d = f1.parse("2012-01-01T00:00:00+0700");
String s1 = f1.format(d); // 2011-12-31T18:00:00+0700
String s2 = f2.format(d); // 2011-12-31T18:00:00+0100

当我在 Android API 7 上运行此代码时,我得到了注释中的值(是的,真的)。此行为取决于特定的 Java 实现。

我的问题是:

  • 为什么 s1 不等于 s2?
  • 更重要的是,为什么 s1 不正确?虽然s2指向一个适当的时间点,s1但没有。Android 的 SimpleDateFormat 实现中似乎存在错误。

问题 1 的答案:参见 BalusC 的答案:

  • [使用后SimpleDateFormat#parse] 之前通过调用 setTimeZone 设置的任何 TimeZone 值可能需要恢复以进行进一步操作。

问题 2的答案:请参阅 wrygiel(我自己)的答案。

  • 这是由于 Android 2.1 (API 7) 中的一个错误造成的。
4

4 回答 4

8

这在 javadoc 中提到DateFormat#parse()

根据给定的解析位置解析日期/时间字符串。例如,一个时间文本"07/10/96 4:5 PM, PDT"将被解析为一个日期,它等同于Date(837039900000L).

默认情况下,解析是宽松的:如果输入不是该对象的格式方法使用的格式,但仍然可以解析为日期,则解析成功。客户可致电setLenient(false).

此解析操作使用calendar来生成Date. 因此,calendar's日期时间字段和TimeZone值可能已被覆盖,具体取决于子类实现。TimeZone之前通过调用设置的任何值都setTimeZone可能需要恢复以进行进一步操作。

注意最后一段。不幸的是,它没有解释何时会发生这种情况。要解决您的特定问题,您需要在格式化操作之前明确设置所需的时区。

至于其自身的可变性SimpleDateFormat,这是众所周知的多年。您永远不应将其实例创建并分配为静态或类变量,而应始终作为方法(线程本地)变量。

于 2012-05-16T18:56:37.827 回答
6

这是由于Android 2.1 (API 7) 中的一个错误造成的。似乎 Android 程序员在他们的 Android 2.1 实现中遗漏了一些未记录的 Java 行为(其本身被归类为不可修复的错误!)。

于 2012-05-16T20:09:27.843 回答
0

你的问题引起了我的兴趣,所以我继续编译你的代码。结果?正如所料...

2011-12-31T18:00:00+0100
2011-12-31T18:00:00+0100

这两个值是相同的,你是在使用一些并发吗?也许变量在f2.format(d).

于 2012-05-16T18:54:14.630 回答
0

我试图通过运行相同的程序来比较 s1 和 s2。他们和我一样。 在此处输入图像描述

于 2012-05-16T19:05:51.033 回答