calendar.add更改时区



在以下代码中,range仅在range小于30时等于durationInDays。如果它等于30或更高,则durationInDays始终为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

为什么then具有IST时区?这种差异是导致duration的少于35天,舍入到34。

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

查看在调试器中如何呈现您的两个Date对象,人们可能会想知道它看起来会以两个不同的时区渲染。他们不是。两者都在欧洲/都柏林时区。您可能知道,爱尔兰大部分欧盟在三月的最后一个星期日切换到夏季时间(DST(。因此,您在2月份的日期是标准时间,在爱尔兰,与GMT相吻合,因此您的字符串用GMT作为"时区"呈现。在3月30日,夏季有效,因此这段时间的爱尔兰夏季时间将时区作为IST。编辑:与您的预期持续时间为35天(840小时(相比,到夏季时间的横向也是缺少的小时。

编辑:由于您可以使用java.time,现代Java日期和时间API,所以我建议您全力以赴,忘记老式的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主要用于几个小时,分钟和秒的时间。它确实支持天数,但每个小时只有几天,因此在整个夏季过渡中使用时会看到令人惊讶的结果。另一方面,ChronoUnit.DAYS完全制造了几天。它看到两个ZonedDateTime实例的时间相同,因此确认两者之间的整整35天。

相关内容

  • 没有找到相关文章

最新更新