Java日历的日间轻量级问题

时间:2018-03-11 12:58:02

标签: java dst java.util.date java.util.calendar

这是关于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.然后有一个逻辑将此时间添加到Calendar对象,其值为' 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"我知道从今天开始,夏令时将提前一小时。任何人都可以帮我理解这个

感谢帮助。

2 个答案:

答案 0 :(得分:3)

今天00:00:00(2018年3月11日星期日)夏季时间(夏令时)尚未生效,所以时间正确呈现为Sun Mar 11 00:00:00 EST 2018(东部标准的EST)时间)。 Date.toString根据Date对象中包含的时间(不基于调用toString方法的时间)在EST和EDT之间进行选择。当你在那个时间增加3个小时时,你将时钟转换为2时的2时间。因此,在你的开始时间后3小时,时间是美国东部夏令时间04:00:00(美国东部时间夏令时间)。

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的时区设置,您可以将zone设置为ZoneId.systemDefault()。这很脆弱,因为程序的其他部分或在同一JVM中运行的其他程序可能随时更改该设置。

将时间设置为午夜后的3小时49分钟(与DST过渡不一样,如您所见):

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

这次我得到了

  

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

答案 1 :(得分:1)

EST为-5,EDT为-4,因此当您调用add()时,您将获得1小时。 如果您需要不同时区的结果,则可以使用scheduleDateCal.set(Calendar.HOUR_OF_DAY, schAdminHour)scheduleDateCal.set(Calendar.MINUTE, schAdminMinute)