Calendar.add更改时区

时间:2018-02-23 23:48:38

标签: java time calendar timezone

在以下代码中,range仅在durationInDays小于30时等于range。如果等于30或更高,则durationInDays始终为{{1} }}

range - 1

调试此示例时,变量设置如下:

Calendar c = Calendar.getInstance();
Date now = new Date();
c.setTime(now);

int range = 35;
c.add(Calendar.DATE, range);
Date then = c.getTime();

Duration duration = Duration.between(now.toInstant(), then.toInstant());
int durationInDays = (int)duration.toDays();

为什么this = {CalTest@871} c = {GregorianCalendar@876} "java.util.GregorianCalendar[time=1522449516301,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Dublin",offset=0,dstSavings=3600000,useDaylight=true,transitions=228,lastRule=java.util.SimpleTimeZone[id=Europe/Dublin,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2018,MONTH=2,WEEK_OF_YEAR=13,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=89,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=38,SECOND=36,MILLISECOND=301,ZONE_OFFSET=0,DST_OFFSET=3600000]" now = {Date@877} "Fri Feb 23 23:38:36 GMT 2018" range = 35 then = {Date@878} "Fri Mar 30 23:38:36 IST 2018" duration = {Duration@879} "PT839H" durationInDays = 34 有IST时区?这种差异导致then小于35天,四舍五入到34。

1 个答案:

答案 0 :(得分:1)

首先,then没有获得IST时区。 Date没有任何时区。 Date.toString选择一个时区,通常是JVM的时区设置,仅用于生成字符串。

看看你的两个Date对象是如何在调试器中呈现的,人们可能会想知道它们会在两个不同的时区中呈现。他们不是。两者都在欧洲/都柏林时区。你可能已经知道,大多数欧盟的爱尔兰在3月的最后一个星期天转为夏令时(夏令时)。因此,您在二月份的日期是标准时间,在爱尔兰与GMT一致,因此您的字符串将以GMT作为“时区”呈现。 3月30日,夏令时生效,因此这次爱尔兰夏令时的时区为IST。编辑:与您预计的35天(840小时)的持续时间相比,夏季时间的转换也会计入缺失的小时数。

编辑:由于您可以使用现代Java日期和时间API java.time,我建议您全力以赴,忘掉旧式DateCalendar。现代API可以更好地使用,您不再需要所有转换:

    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Dublin"));
    int range = 35;
    ZonedDateTime then = now.plusDays(range);
    Duration duration = Duration.between(now, then);
    int durationInDays = (int) duration.toDays();

结果仍然是PT839H,因此是34天。

获取与我们添加的天数一致的天数:

    int durationInDays = (int) ChronoUnit.DAYS.between(now, then);
    System.out.println(durationInDays);

打印

35

Duration主要用于以小时,分钟和秒为单位的持续时间。它确实支持天数,但每天只有24小时,所以给出了在夏季时间过渡时使用的惊人结果。另一方面,ChronoUnit.DAYS完全是为了好几天。它看到两个ZonedDateTime实例具有相同的时间,因此承认两者之间有完整的35天。