【问题标题】:Java GregorianCalendar and DST Cutover TimesJava GregorianCalendar 和 DST 切换时间
【发布时间】:2023-03-06 02:09:01
【问题描述】:

我有一个 GregorianCalendar,我正在尝试设置时间。我从一个日历中获取日期,从另一个日历中获取时间。除了 DST 切换日的凌晨 2 点之外,它大部分都有效。

例如,日期为 2013 年 3 月 10 日,时间为凌晨 2:40,目标输出为 2013 年 3 月 10 日凌晨 2:40,我得到 2013 年 3 月 10 日凌晨 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。我希望它不要切换。我认为这与将目标时间日历创建为纪元日期的时间有关,但我希望目标时间的具体日期并不重要......

【问题讨论】:

  • 我遇到了类似的问题,这是因为您的 PC 的时区不支持应用从标准时间更改为夏令时 (DST) 的日期的凌晨 2:00,例如(UTC-06:00) 中部时间(美国和加拿大)。我什至尝试使用 joda 库但没有成功(也许我没有付出足够的努力)。我也想得到这个话题的答案。
  • 几年过去了,“这就是时间的运作方式”这样的答案让我心平气和,你失去了一个小时。就是这样。我的用户非常非常困惑,但是一些解释和他们在同一页上。更多关于取消夏令时的论据!

标签: java time calendar


【解决方案1】:

基于此输出...我认为这正是 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 认为偏移量会在凌晨 2-3 点从 0400 变为 0500(这是针对 EST),因此不会浪费时间,但您不能用 0400 偏移量表示 2013 年 3 月 10 日凌晨 2 点,因为它不存在跨度>
【解决方案2】:

您正在设置所有内容,但时区(包含 DST)除外。也设置它,你应该没问题。

【讨论】:

  • 这是我遇到类似问题时的解决方案。非常抱歉。
  • 这不是一个解决方案,因为当您使用combination.getTime() 时,它将返回一个新的Date 对象,并应用了 pc/server 时区,因此在日历上所做的时区更改不会有什么效果。
【解决方案3】:

这并不是直接回答您的问题,但您可以通过Joda Time 避免所有这些疯狂

他们确实确定了日期/时间/日历。

【讨论】:

  • 如果你发布一个例子,那就太好了。
猜你喜欢
  • 2012-10-28
  • 2013-03-02
  • 2011-12-24
  • 1970-01-01
  • 2013-04-15
  • 2012-08-21
  • 2019-04-30
  • 2016-04-05
  • 2020-09-22
相关资源
最近更新 更多