为什么这个日历会失败?

时间:2013-09-19 20:56:18

标签: java date calendar

所以我有一个尊重你的时区的Java应用程序,我注意到一些时区有无效日期......

我正在使用SimpleDateFormatter('yyyyMMdd')进行解析...并发现它在某些时区 - 日期组合上失败并显示ParseException

我查看了内部,看起来它失败了,因为Calendar类正在抛出IllegalArgumentException

我使用setLenient(false),因为我不想让解析做出假设。使用setLenient(true)的默认值假定缺少字段,并且不会抛出IllegalArgumentException

为什么这个有效:

 public void testCalendarPass() {
    Calendar cal = Calendar.getInstance();
    cal.clear();
    cal.setLenient(false);
    cal.set(Calendar.YEAR, 1995);
    cal.set(Calendar.MONTH, Calendar.JANUARY);
    cal.set(Calendar.DAY_OF_MONTH,1);

    //This call will pass
    cal.getTime();
}

虽然太平洋/ Kiritimati的这个失败了:

public void testCalendarFailure() {
    Calendar cal = Calendar.getInstance();
    cal.clear();
    cal.setTimeZone(TimeZone.getTimeZone("Pacific/Kiritimati"));
    cal.setLenient(false);
    cal.set(Calendar.YEAR, 1995);
    cal.set(Calendar.MONTH, Calendar.JANUARY);
    cal.set(Calendar.DAY_OF_MONTH,1);

    //This call will fail
    cal.getTime();
}

1995年1月1日在Kiritimati不存在吗?他们如何引用属于该差距的时间?

现在,当我遇到ParseException时,我默认使用服务器的时区进行解析。但这会导致最多24小时的偏移(取决于时区)。

此处列出了其他时区失败的其他日期:

19930820 FAILS on Kwajalein
19930820 FAILS on Pacific/Kwajalein
20111230 FAILS on MIT
20111230 FAILS on Pacific/Apia
19950101 FAILS on Pacific/Enderbury
20111230 FAILS on Pacific/Fakaofo
19950101 FAILS on Pacific/Kiritimati

2 个答案:

答案 0 :(得分:1)

因为1月1日基里马蒂遭遇24小时轮班。 The Republic of Kiribati, in the Central Pacific, introduced a change of date for its eastern half on 1 January 1995, from time zones UTC−11 and UTC−10 to UTC+13 and UTC+14. Before this, the country was divided by the IDL. After the change, the IDL in effect moved eastwards to go around this country. http://en.wikipedia.org/wiki/International_Date_Line#Eastern_Kiribati

另外,我看了一眼阿皮亚,似乎是:At 0000 local 30 December 2011 the clocks were moved 24 hours ahead http://en.wikipedia.org/wiki/Apia

显然,由于24小时轮班,这两个日期实际上并不存在于相应时区的日历中。对所有其他人来说可能都是如此。

答案 1 :(得分:0)

编辑:我最初认为Java没有认识到“太平洋/ Kiritimati”的含义。但事实证明确实如此。要获取Java将识别的所有字符串的列表,请使用:

Set<String> ids = new TreeSet<String>();
for (String id : TimeZone.getAvailableIDs())
   ids.add(id);
for (String id : ids)
  System.out.println(id);