Java GregorianCalendar和DST切换时间

Java GregorianCalendar和DST切换时间,java,time,calendar,Java,Time,Calendar,我有一个格雷戈里安日历,我正试图设定时间。我从一个日历中获取日期,从另一个日历中获取时间。除DST转换日凌晨2点外,它基本上都能工作 例如,日期为2013年10月3日,时间为凌晨2:40,目标输出为2013年10月3日凌晨2:40,我得到2013年10月3日凌晨3:40: GregorianCalendar reportingDate = //some instance with a relevant date (in this case 3/10/2013) GregorianCalendar

我有一个格雷戈里安日历,我正试图设定时间。我从一个日历中获取日期,从另一个日历中获取时间。除DST转换日凌晨2点外,它基本上都能工作

例如,日期为2013年10月3日,时间为凌晨2:40,目标输出为2013年10月3日凌晨2:40,我得到2013年10月3日凌晨3:40:

GregorianCalendar reportingDate = //some instance with a relevant date (in this case 3/10/2013)
GregorianCalendar targetTime = //some instance with a relevant time (in this case 2:40AM)
Calendar combination = Calendar.getInstance();
combination.set(Calendar.YEAR, reportingDate.get(Calendar.YEAR));
combination.set(Calendar.MONTH, reportingDate.get(Calendar.MONTH));
combination.set(Calendar.DAY_OF_YEAR, reportingDate.get(Calendar.DAY_OF_YEAR));
combination.set(Calendar.HOUR, targetTime.get(Calendar.HOUR));
combination.set(Calendar.AM_PM, targetTime.get(Calendar.AM_PM));
combination.set(Calendar.MINUTE, targetTime.get(Calendar.MINUTE));
combination.set(Calendar.SECOND, targetTime.get(Calendar.SECOND));

一旦代码在组合日历上设置了AM_PM,时间就会切换到凌晨3:40。我希望它不要切换。我认为这与目标时间日历被创建为纪元日期上的时间有关,但我希望目标时间的具体日期不太重要…

您正在设置所有内容,除了时区(包含DST)。设置好它,你就会没事。

你正在设置所有东西,除了时区(包含DST)。设置好它,你应该会没事的。

这并不是直接回答你的问题,但你可以通过使用


他们确实把日期/时间/日历的事情搞定了

这并不是直接回答你的问题,但你可以通过选择


他们确实把日期/时间/日历的事情搞定了

基于此输出。。。我想这就是Java处理DST的方式?好像凌晨2点到3点就被遗忘了

见下面我的评论

final Calendar reportingDate = Calendar.getInstance();
reportingDate.set(Calendar.YEAR, 2013);
reportingDate.set(Calendar.MONTH, Calendar.MARCH);
reportingDate.set(Calendar.DAY_OF_MONTH, 10);

final Calendar targetTime = Calendar.getInstance();
targetTime.set(Calendar.AM_PM, Calendar.AM);
targetTime.set(Calendar.HOUR_OF_DAY, 3);
targetTime.set(Calendar.MINUTE, 0);
targetTime.set(Calendar.SECOND, 0);
targetTime.set(Calendar.MILLISECOND, 0);

final Calendar combination = Calendar.getInstance();
combination.set(Calendar.YEAR, reportingDate.get(Calendar.YEAR));
combination.set(Calendar.MONTH, reportingDate.get(Calendar.MONTH));
combination.set(Calendar.DAY_OF_YEAR, reportingDate.get(Calendar.DAY_OF_YEAR));
combination.set(Calendar.HOUR, targetTime.get(Calendar.HOUR));
combination.set(Calendar.AM_PM, targetTime.get(Calendar.AM_PM));
combination.set(Calendar.MINUTE, targetTime.get(Calendar.MINUTE));
combination.set(Calendar.SECOND, targetTime.get(Calendar.SECOND));
combination.set(Calendar.MILLISECOND, targetTime.get(Calendar.MILLISECOND));

final long timeAtCombined = combination.getTimeInMillis();

final SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSSZ");
sdf.setTimeZone(TimeZone.getTimeZone("US/Eastern"));

// subtract one minute
System.out.println(sdf.format(combination.getTime()));
combination.add(Calendar.MILLISECOND, -1);
System.out.println(sdf.format(combination.getTime()));

// millis @ 3
System.out.println(sdf.format(new Date(timeAtCombined)));
// millis @ 3 - 1ms
System.out.println(sdf.format(new Date(timeAtCombined - 1)));
输出

03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500
03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500

基于此输出。。。我想这就是Java处理DST的方式?好像凌晨2点到3点就被遗忘了

见下面我的评论

final Calendar reportingDate = Calendar.getInstance();
reportingDate.set(Calendar.YEAR, 2013);
reportingDate.set(Calendar.MONTH, Calendar.MARCH);
reportingDate.set(Calendar.DAY_OF_MONTH, 10);

final Calendar targetTime = Calendar.getInstance();
targetTime.set(Calendar.AM_PM, Calendar.AM);
targetTime.set(Calendar.HOUR_OF_DAY, 3);
targetTime.set(Calendar.MINUTE, 0);
targetTime.set(Calendar.SECOND, 0);
targetTime.set(Calendar.MILLISECOND, 0);

final Calendar combination = Calendar.getInstance();
combination.set(Calendar.YEAR, reportingDate.get(Calendar.YEAR));
combination.set(Calendar.MONTH, reportingDate.get(Calendar.MONTH));
combination.set(Calendar.DAY_OF_YEAR, reportingDate.get(Calendar.DAY_OF_YEAR));
combination.set(Calendar.HOUR, targetTime.get(Calendar.HOUR));
combination.set(Calendar.AM_PM, targetTime.get(Calendar.AM_PM));
combination.set(Calendar.MINUTE, targetTime.get(Calendar.MINUTE));
combination.set(Calendar.SECOND, targetTime.get(Calendar.SECOND));
combination.set(Calendar.MILLISECOND, targetTime.get(Calendar.MILLISECOND));

final long timeAtCombined = combination.getTimeInMillis();

final SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSSZ");
sdf.setTimeZone(TimeZone.getTimeZone("US/Eastern"));

// subtract one minute
System.out.println(sdf.format(combination.getTime()));
combination.add(Calendar.MILLISECOND, -1);
System.out.println(sdf.format(combination.getTime()));

// millis @ 3
System.out.println(sdf.format(new Date(timeAtCombined)));
// millis @ 3 - 1ms
System.out.println(sdf.format(new Date(timeAtCombined - 1)));
输出

03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500
03/10/2013 03:00:00.000-0400
03/10/2013 01:59:59.999-0500

我遇到了一个类似的问题,这是因为您电脑的时区不支持将标准时间更改为夏令时(DST)的日期的凌晨2点,例如(UTC-06:00)中央时间(美国和加拿大)。我甚至尝试使用joda library都没有成功(可能是我没有付出足够的努力)。我也想得到一个关于这个话题的答案。几年过去了,我平静地回答说“时间就是这样工作的”,你会损失一个小时。事实就是这样。我的用户非常非常困惑,但是一些解释和他们在同一页上。更多关于取消夏令时的争论!我遇到了一个类似的问题,这是因为您电脑的时区不支持将标准时间更改为夏令时(DST)的日期的凌晨2点,例如(UTC-06:00)中央时间(美国和加拿大)。我甚至尝试使用joda library都没有成功(可能是我没有付出足够的努力)。我也想得到一个关于这个话题的答案。几年过去了,我平静地回答说“时间就是这样工作的”,你会损失一个小时。事实就是这样。我的用户非常非常困惑,但是一些解释和他们在同一页上。更多关于取消夏令时的争论!如果你发一个例子,那就太好了。如果你发一个例子,那就太好了。这就是我遇到类似问题时的解决方案。非常抱歉。这不是一个解决方案,因为当您使用
composition.getTime()
时,它将返回一个新的
Date
对象,并应用pc/服务器时区,因此对日历所做的时区更改将不会产生任何影响。这就是我遇到类似问题时的解决方案。非常抱歉。这不是一个解决方案,因为当您使用
composition.getTime()
时,它将返回一个新的
Date
对象,并应用pc/服务器时区,因此在日历上所做的时区更改不会产生任何影响。实际上,我刚刚注意到“遗忘”的位置。。当然,偏移量在当时会发生变化。Java认为偏移量会在凌晨2-3点从0400变为0500(这是针对EST的),因此不会浪费时间,但不能用0400偏移量表示2013年10月3日凌晨2点的EST,因为它实际上不存在,我只是注意到了“遗忘”的位置。。当然,偏移量在当时会发生变化。Java认为偏移量将在凌晨2-3点从0400更改为0500(这是针对EST),因此不会浪费时间,但不能用0400偏移量表示2013年10月3日凌晨2点的EST,因为它不存在