在夏令时(America / Los_Angeles),如果我加一天,它只增加23小时而不是24小时

时间:2017-02-02 07:46:58

标签: java dst

以下是示例代码

public class DateFormatSampleCode {
    public static void main(String[] args) throws ParseException {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
        cal.setTime(sdf.parse("2016-03-12T02:00:00-0800"));
        sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
        System.out.println(sdf.format(cal.getTime()));
        cal.add(Calendar.DATE, 1);
        System.out.println(sdf.format(cal.getTime()));  
    }
}

这里的答案是

  

“2016-03-12T01:00:00-0800”

,但从我的观点来看,它应该是“

  

2016-03-12T03:00:00-0700

”。

1 个答案:

答案 0 :(得分:2)

如您所知,“2016年夏令时(DST)从2016年3月13日凌晨2点(当地时间)至2016年11月6日凌晨2点(当地时间)生效”({{3} })。因此,如果您在3月12日凌晨2点之前添加24小时,那么您可以准确地将时钟从2点移到凌晨3点。因此,我认为不太清楚结果是什么。我会立即期待02:00:00-080003:00:00-0700(后者是您的预期)。

您正在使用pre-Java-8 Calendar类。如果结果准确记录,我就错过了。该文档仅表示添加“基于日历的规则”。考虑到这个问题,如果你从3月12日的2到3岁之间开始,那么问题就是期待。在2之前,你将在3月13日,24小时后获得相同的时间。 3之后也很容易,你得到的是同一时间,只有23小时后因为变化。对于2到3之间的时间,3月13日不存在相同的时间,因此必须做出选择。似乎选择减去一个小时。他们还选择在凌晨2:00进行此操作,但不是在3:00:00进行此操作,以使规则在半小时开放的时间间隔内有效。至少这是一致的。我们可能无法完全避免意外结果。

例如java.time之类的Java 8 ZonedDateTime类更好地记录,因此更可靠。例如,ZonedDateTime.plusDays()会将day / s添加到本地日期时间并转换回ZonedDateTime。如果本地日期时间在间隙(如此处),则“将通过间隙的长度向前调整”(此处为1小时)。因此,您的结果将是2016-03-13T03:00-07:00[America/Los_Angeles],与您预期的完全一样。

要学习的一个可能的教训是,如果可以使用Java 8,请使用java.time类。