Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java日历中的未来日期给出了一种奇怪的行为_Java_Date_Calendar_Timezone - Fatal编程技术网

java日历中的未来日期给出了一种奇怪的行为

java日历中的未来日期给出了一种奇怪的行为,java,date,calendar,timezone,Java,Date,Calendar,Timezone,我有一个应用程序,我创建的日期,用户可以选择一个约会。如果一个用户在9点开始工作,一个约会需要2个小时,我会在9点、11点、13点创建日期。。。当然,直到极限。然后我改变了一天,重新开始。 这是执行此操作的代码: public List<Agenda> createListOfDates(Calendar initial, Calendar end, int appointmentDuration, int lunchTimeDuration, int lu

我有一个应用程序,我创建的日期,用户可以选择一个约会。如果一个用户在9点开始工作,一个约会需要2个小时,我会在9点、11点、13点创建日期。。。当然,直到极限。然后我改变了一天,重新开始。 这是执行此操作的代码:

    public List<Agenda> createListOfDates(Calendar initial, Calendar end, 
        int appointmentDuration, int lunchTimeDuration, int lunchTimeStart) {

        List<Agenda> agendaList = new ArrayList<Agenda>();

        Agenda agenda = new Agenda();
        agenda.setWorkingHour(initial.getTime());
        agendaList.add(agenda);
        while (true) {

            initial.add(Calendar.HOUR_OF_DAY, appointmentDuration);
//          Logger.error("" + initial.getTime());

            if (initial.getTime().after(end.getTime())) {
                break;

            } else if (initial.get(Calendar.HOUR_OF_DAY) == lunchTimeStart
                    && initial.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
                    ) {
                initial.add(Calendar.HOUR_OF_DAY, lunchTimeDuration);
                agenda = new Agenda();
                agenda.setWorkingHour(initial.getTime());
                agendaList.add(agenda);

            } else {
                agenda = new Agenda();
                agenda.setWorkingHour(initial.getTime());
                agendaList.add(agenda);
            }
        }

        for(Agenda agendaX : agendaList){
        Logger.info("" + agendaX.getWorkingHour());

}

        return agendaList;
    }

虽然是在格林尼治标准时间,这是正确的,但我不能理解这个英国夏令时。是不是因为它在未来太多了?它总是从四月开始。

您的系统时间不是格林尼治标准时间,而是欧洲/伦敦(或类似的时间)。3月份伦敦时间与格林尼治标准时间一致,而不是4月份。这就是为什么

getWorkingHour()
返回
Date
的一个实例(另一个设计拙劣且过时很长的类,但现在让它成为另一个故事)。将其附加到空字符串后,将隐式调用
Date.toString
,并使用系统时区生成字符串。在标准时间内,它将
GMT
打印为时区缩写。夏季时间(DST)从伦敦3月的最后一个星期日开始,在本例中为3月31日。因此,在JVM上的4月
Date.toString
使用英国夏季时间及其缩写
BST
来打印时间

好的解决方案包括两个变化:

  • 不要依赖JVM的默认时区。它可以随时从程序的另一部分或运行在同一JVM中的另一个程序进行更改,因此太脆弱了。相反,为日期时间操作指定明确的时区
  • 跳过旧的日期时间类
    Calendar
    date
    ,而是使用java.time,即现代的java日期和时间API。使用它更好,代码更清晰,尤其是在时区转换方面
  • 不要使用
    Calendar
    而使用
    zoneDateTime
    。根据JDBC驱动程序的功能,将其转换为UTC格式的
    Instant
    OffsetDateTime
    ,以保存到数据库中

    要创建
    ZoneDateTime
    ,一个选项是使用其
    of
    方法之一(有几种):

    这将在圣保罗创建2019年3月10日09:00的日期时间。要在其中添加2小时,请执行以下操作:

        int appointmentDuration = 2;
        ZonedDateTime current = initial.plusHours(appointmentDuration);
        System.out.println(current);
    
    输出:

    2019-03-10T11:00-03:00[美国/圣保罗]

    要将数据库转换为
    即时

        Instant inst = current.toInstant();
        System.out.println(inst);
    
    输出:

    2019-03-10T14:00:00Z

    瞬间与时区无关,只是一个时间点,但以UTC打印。一些JDBC驱动程序接受UTC时间。如果您的设置不符合要求,则需要为其设置一个
    OffsetDateTime
    。像这样转换:

        OffsetDateTime odt = current.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odt);
    
    输出:

    2019-03-10T14:00Z


    注意,我显式地给出了UTC,而不是依赖于JVM默认值。所以这在UTC中是明确的。您注意到日期和时间与从
    Instant

    打印的日期和时间一致。您的系统时间不是GMT,而是欧洲/伦敦(或类似的地方)。3月份伦敦时间与格林尼治标准时间一致,而不是4月份。这就是为什么

    getWorkingHour()
    返回
    Date
    的一个实例(另一个设计拙劣且过时很长的类,但现在让它成为另一个故事)。将其附加到空字符串后,将隐式调用
    Date.toString
    ,并使用系统时区生成字符串。在标准时间内,它将
    GMT
    打印为时区缩写。夏季时间(DST)从伦敦3月的最后一个星期日开始,在本例中为3月31日。因此,在JVM上的4月
    Date.toString
    使用英国夏季时间及其缩写
    BST
    来打印时间

    好的解决方案包括两个变化:

  • 不要依赖JVM的默认时区。它可以随时从程序的另一部分或运行在同一JVM中的另一个程序进行更改,因此太脆弱了。相反,为日期时间操作指定明确的时区
  • 跳过旧的日期时间类
    Calendar
    date
    ,而是使用java.time,即现代的java日期和时间API。使用它更好,代码更清晰,尤其是在时区转换方面
  • 不要使用
    Calendar
    而使用
    zoneDateTime
    。根据JDBC驱动程序的功能,将其转换为UTC格式的
    Instant
    OffsetDateTime
    ,以保存到数据库中

    要创建
    ZoneDateTime
    ,一个选项是使用其
    of
    方法之一(有几种):

    这将在圣保罗创建2019年3月10日09:00的日期时间。要在其中添加2小时,请执行以下操作:

        int appointmentDuration = 2;
        ZonedDateTime current = initial.plusHours(appointmentDuration);
        System.out.println(current);
    
    输出:

    2019-03-10T11:00-03:00[美国/圣保罗]

    要将数据库转换为
    即时

        Instant inst = current.toInstant();
        System.out.println(inst);
    
    输出:

    2019-03-10T14:00:00Z

    瞬间与时区无关,只是一个时间点,但以UTC打印。一些JDBC驱动程序接受UTC时间。如果您的设置不符合要求,则需要为其设置一个
    OffsetDateTime
    。像这样转换:

        OffsetDateTime odt = current.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odt);
    
    输出:

    2019-03-10T14:00Z


    注意,我显式地给出了UTC,而不是依赖于JVM默认值。所以这在UTC中是明确的。您注意到日期和时间与从
    Instant

    BST
    =“现在我明白了。非常感谢。我现在对另一件事有一个疑问:为什么你们写那个日期是“另一个设计拙劣、过时很久的课程,但现在让它成为一个不同的故事”?现在我明白了。非常感谢。我现在对另一件事有一个疑问:为什么你认为这个日期是“另一个设计拙劣、过时很久的课程,但现在就让它成为一个不同的故事”?