Java日历的日光节约问题

Java日历的日光节约问题,java,dst,java.util.date,java.util.calendar,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.MIN

这是关于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”的Calendar对象中,并使用下面的语句

scheduleDateCal.add(Calendar.HOUR_OF_DAY, schAdminHour);
理论上,在该计算之后,日历对象的值应为“Sun Mar 11 03:00:00 EDT 2018”。但是它返回“Sun Mar 11 04:00:00 EDT 2018”,我知道从今天开始,夏令时将提前一小时。有谁能帮我理解这一点吗


感谢您的帮助。

东部标准时间为-5,东部标准时间为-4,因此您在调用add()时有1小时的时间。
您可以使用
scheduleDateCal.set(Calendar.HOUR OF_DAY,schAdminHour)
scheduleDateCal.set(Calendar.MINUTE,schAdminMinute)
,如果您需要不同时区的结果。

东部标准时间为-5,东部标准时间为-4,因此您在调用add()时可以得到1小时。 如果您需要不同时区的结果,可以使用
scheduleDateCal.set(Calendar.HOUR OF_DAY,schAdminHour)
scheduleDateCal.set(Calendar.MINUTE,schAdminMinute)

今天(2018年3月11日星期日)00:00的夏季时间(DST)尚未生效,因此,该时间被正确渲染为2018年3月11日太阳00:00:00东部标准时间(东部标准时间)
Date.toString
根据
Date
对象中包含的时间(而不是根据调用
toString
方法的时间)在EST和EDT之间进行选择。如果在该时间上加上3小时,则将时钟向前拨到3时,在2处穿过该时间。因此,在开始时间3小时后,时间是美国东部夏令时04:00:00(东部夏令时)

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转换不同):

这次我得到了

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

今天00:00:00(2018年3月11日星期日)的夏季时间(DST)尚未生效,因此该时间被正确渲染为2018年3月11日太阳00:00:00东部标准时间(东部标准时间)
Date.toString
根据
Date
对象中包含的时间(而不是根据调用
toString
方法的时间)在EST和EDT之间进行选择。如果在该时间上加上3小时,则将时钟向前拨到3时,在2处穿过该时间。因此,在开始时间3小时后,时间是美国东部夏令时04:00:00(东部夏令时)

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转换不同):

这次我得到了

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


谢谢你的回复。你知道为什么日期=新日期()吗;重新运行EST(2018年3月11日太阳00:00:00 EST)即使我的时区更改为EDT,您的java版本是新的吗?当地方当局更改夏时制开始/结束规则时,java运行时中包含的时区数据库有时需要更新。您可以使用时区更新工具修补java,请参阅链接:谢谢您的回复。你知道为什么日期=新日期()吗;重新运行EST(2018年3月11日太阳00:00:00 EST)即使我的时区更改为EDT,您的java版本是新的吗?当地方当局更改夏时制开始/结束规则时,java运行时中包含的时区数据库有时需要更新。您可以使用时区更新工具修补java,请参阅链接:您对最佳实践的看法是正确的。对于conveniten未来最早的版本,我建议您改为使用
Calendar
Date
早就过时了,而且现代API使用起来更方便。仅供参考,像、
java.text.SimpleDateFormat
这样麻烦的旧日期时间类现在被java 8和java 9中内置的类所取代。看,关于最佳实践,你是对的。对于conveniten未来最早的版本,我建议您改为使用
Calendar
Date
早就过时了,而且现代API使用起来更方便。仅供参考,像、
java.text.SimpleDateFormat
这样麻烦的旧日期时间类现在被java 8和java 9中内置的类所取代。有关评论,请参见.thanx@Ole V.V。在调试代码时,我发现calendar对象最初是EDT,但在它执行scheduleDateCal.set(calendar.HOUR OF_DAY,0)时;改成了Est,听起来不错。
C的初始值