我发现了有关Java DST更改的问题。当DST(日光节省时间)发生的确切时刻可能会出现两次。
例如,对于时区美国/sao_paulo,它从2016年2月21日(星期日),00:00:00到2016年2月20日(星期六)向后更改了一个小时。那天的时间23:00出现了两次。
在我的用例中,我想第二次。例如,当我想要这一天的数据时,我实际上是说这一天(即使可能包含25小时)。
但我认为,爪哇似乎是这一刻的第一次。
示例:
@Test
public void testDSTChange() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
TimeZone tz = TimeZone.getTimeZone("America/Sao_Paulo");
long dateInput = sdf.parse("2016-02-20T23:00:00").getTime();
long dateUTC = dateInput - tz.getOffset(dateInput);
long dateInput2 = sdf.parse("2016-02-21T02:00:00").getTime();
long dateUTC2 = dateInput2 - tz.getOffset(dateInput2);
System.out.println("Difference: " + (dateUTC2 - dateUTC) / 3600 / 1000);
}
在此示例中,它表明这两个日期之间的差异为4小时,而不是我预期的3个小时。所以我想知道是否还有其他方法可以吗?
好吧,当DST向后更改时,DST更改的时间将发生两次,无法解决。可能会有另一种方法,但是让我提出一个建议,内部使用UTC时间(GMT),它在内部没有DST,仅用于显示目的而将其转换为当地时间(壁时钟时间)。您将不必再担心。
在我的用例中,我想第二次。例如,当我想要这一天的数据时,我实际上是说这一天(即使可能包含25小时)。
。
在此语句中,我假设您实际上正在做某种范围查询以在整天收集数据。解决此问题的最佳方法是从一天开始包含的开始查询,到第二天的开始 exclusive 。换句话说:startOfDay <= dataPoint(s) < startOfNextDay
这在您的情况下效果很好,因为直到第二天开始时,时钟实际上才碰到00:00
。它是这样的:
23:58
23:59
23:00
23:01
...
23:58
23:59
00:00 <--- start of next day
因此,请使用半开的间隔,并且应该奏效。
在春季过渡中要小心,当一天的开始是01:00
而不是00:00
时。:)
此外,乔恩(Jon)关于使用Java 8的新时代API或Joda Time的评论是点对点。他们俩都可以更好地控制这种情况。较旧的Java Apis没有。
LocalDateTime l1 = LocalDateTime.of(2016, Month.FEBRUARY, 20, 23, 0, 0);
ZoneId id = ZoneId.of("America/Sao_Paulo");
ZoneOffset offset = ZoneOffset.of("-08:00");
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(l1, offset, id);
long el1= zonedDateTime.toEpochSecond();
LocalDateTime l2 = LocalDateTime.of(2016, Month.FEBRUARY, 21, 2, 0, 0);
ZonedDateTime zonedDateTime1 = ZonedDateTime.ofInstant(l2, offset, id);;
long el2= zonedDateTime1.toEpochSecond();
System.out.println("Difference: " + (el2-el1 ) / 3600 );
====================================
on console it prints
Difference: 3