0

这是关于 Java 日历以及我们在多伦多今天夏令时更改后遇到的影响。

下面是代码

    Date date = new Date(); //Sun Mar 11 00:00:00 EST 2018
    Integer time = 349;

    Calendar scheduleDateCal = Calendar.getInstance();
    scheduleDateCal.setTime(date);

    scheduleDateCal.set(Calendar.MINUTE, 0);
    scheduleDateCal.set(Calendar.HOUR_OF_DAY, 0);
    String strSchAdminTime = String.valueOf(time);
    Integer schAdminMinute = time;

    if (strSchAdminTime.length() >= 2) {
        schAdminMinute = Integer.valueOf(strSchAdminTime.substring(strSchAdminTime.length()-2));
    } 
    if(time>60){
        Integer schAdminHour = Integer.valueOf(strSchAdminTime.substring(0,strSchAdminTime.length()-2));
        scheduleDateCal.add(Calendar.HOUR_OF_DAY, schAdminHour);
    }else{
        scheduleDateCal.add(Calendar.HOUR_OF_DAY, 0);
    }
    scheduleDateCal.add(Calendar.MINUTE, schAdminMinute);

    System.out.println(scheduleDateCal.getTime());

我知道这段代码没有使用最佳实践,但是我需要为当前版本维护它。在这里,它使用整数来表示时间部分,然后有一个逻辑可以从中提取小时和分钟。

当我遵循逻辑时,小时部分为 3。然后有一个逻辑将此时间添加到日历对象,其值为 'Sun Mar 11 00:00:00 EST 2018' 并带有以下语句

scheduleDateCal.add(Calendar.HOUR_OF_DAY, schAdminHour);

理论上,经过此计算,日历对象的值应为“Sun Mar 11 03:00:00 EDT 2018”。但是它返回“Sun Mar 11 04:00:00 EDT 2018”我知道从今天开始,夏令时时间将提前一小时。谁能帮我理解这一点

感谢帮助。

4

2 回答 2

3

今天(2018 年 3 月 11 日星期日)00:00:00 夏令时 (DST) 尚未生效,因此该时间正确呈现为 2018 年 3 月 11 日星期日 00:00:00 EST(东部标准时间为 EST)。根据对象中包含的时间(而不是基于调用方法的时间)Date.toString在 EST 和 EDT 之间进行选择。当您在该时间上增加 3 小时时,您在 2 处越过时间,此时时钟被调快到 3。因此,在您的开始时间 3 小时后,时间是美国东部夏令时间 04:00:00(美国东部夏令时间)。DatetoString

PS现代代码

PS 如果您或其他人有兴趣,这里是您的代码的现代版本——既简单又短。要将时间设置为 03:49:

    int time = 349;
    ZoneId zone = ZoneId.of("America/Toronto");
    ZonedDateTime scheduledDateTime = LocalDate.now(zone)
            .atTime(time / 100, time % 100)
            .atZone(zone);
    System.out.println(scheduledDateTime);

今天这个印

2018-03-11T03:49-04:00[美国/多伦多]

当然,更好的是,如果您可以完全摆脱将 03:49 表示为整数值 349。要使用 JVM 的时区设置,您可以设置zoneZoneId.systemDefault(). 这是脆弱的,因为您的程序的其他部分或在同一 JVM 中运行的其他程序可能随时更改设置。

将时间设置为午夜后 3 小时 49 分钟(正如您所见,与 DST 转换不同):

    ZonedDateTime scheduledDateTime = LocalDate.now(zone)
            .atStartOfDay(zone)
            .plusHours(time / 100)
            .plusMinutes(time % 100);

这次我得到了

2018-03-11T04:49-04:00[美国/多伦多]

于 2018-03-11T13:39:37.533 回答
1

EST 是 -5,EDT 是 -4,所以当你调用 add() 时你会得到 1 小时。如果需要不同时区的结果,您可以使用scheduleDateCal.set(Calendar.HOUR_OF_DAY, schAdminHour)and 。scheduleDateCal.set(Calendar.MINUTE, schAdminMinute)

于 2018-03-11T13:10:25.867 回答