将GregorianCalendar转换为DST当天的日期? [英] Converting GregorianCalendar to Date on day of DST loses an hour?
问题描述
我正在解决将仅代表当前日期(即,2013-03-10 00:00:00)的GregorianCalendar转换为java.util.Date对象的问题。这个测试背后的想法是采用两个日期 - 一个只有当前日期,一个只有当前时间(即// 1970-01-01 12:30:45),并将它们组合成一个表示日期的日期和时间(2013-03-10 12:30:45)。
I'm troubleshooting an issue with converting a GregorianCalendar that only represents the current date (ie// 2013-03-10 00:00:00) to a java.util.Date object. The idea behind this test is to take two dates - one with only the current date, and one with only the current time (ie// 1970-01-01 12:30:45), and combine them into one date representing the Date and Time (2013-03-10 12:30:45).
在发生DST切换的那一天,测试失败 - 因为将GregorianCalendar转换为日期对象(Date date = dateCal.getTime();在下面的代码中)失去了一个小时,因此回滚到(2013-03-09 23:00:00)。如何使这不会发生?
On the day when the DST switch occured, the test failed - because converting the GregorianCalendar to a date object (Date date = dateCal.getTime(); in the code below) lost an hour and thus rolled back to (2013-03-09 23:00:00). How can I make this not happen?
public static Date addTimeToDate(Date date, Date time) {
if (date == null) {
throw new IllegalArgumentException("date cannot be null");
} else if (time == null) {
throw new IllegalArgumentException("time cannot be null");
} else {
Calendar timeCal = GregorianCalendar.getInstance();
timeCal.setTime(time);
long timeMs = timeCal.getTimeInMillis() + timeCal.get(Calendar.ZONE_OFFSET) + timeCal.get(Calendar.DST_OFFSET);
return addMillisecondsToDate(date, timeMs);
}
}
@Test
public void testAddTimeToDate() {
Calendar expectedCal = Calendar.getInstance();
Calendar dateCal = Calendar.getInstance();
dateCal.clear();
dateCal.set(expectedCal.get(Calendar.YEAR), expectedCal.get(Calendar.MONTH), expectedCal.get(Calendar.DAY_OF_MONTH));
Calendar timeCal = Calendar.getInstance();
timeCal.clear();
timeCal.set(Calendar.HOUR_OF_DAY, expectedCal.get(Calendar.HOUR_OF_DAY));
timeCal.set(Calendar.MINUTE, expectedCal.get(Calendar.MINUTE));
timeCal.set(Calendar.SECOND, expectedCal.get(Calendar.SECOND));
timeCal.set(Calendar.MILLISECOND, expectedCal.get(Calendar.MILLISECOND));
Date expectedDate = expectedCal.getTime();
Date date = dateCal.getTime();
Date time = timeCal.getTime();
Date actualDate = DateUtil.addTimeToDate(date, time);
assertEquals(expectedDate, actualDate);
}
推荐答案
重构我的方法来补偿由于DST导致的丢失/获得的小时数:
This is how I ended up refactoring my method to compensate for the lost / gained hour due to DST:
public static Date addTimeToDate(Date date, Date time) {
if (date == null) {
throw new IllegalArgumentException("date cannot be null");
} else if (time == null) {
throw new IllegalArgumentException("time cannot be null");
} else {
Calendar dateCal = GregorianCalendar.getInstance();
dateCal.setTime(date);
Calendar timeCal = GregorianCalendar.getInstance();
timeCal.setTime(time);
int zoneOffset = timeCal.get(Calendar.ZONE_OFFSET);
if (dateCal.get(Calendar.MONTH) == Calendar.MARCH) {
if (Calendar.SUNDAY == dateCal.get(Calendar.DAY_OF_WEEK) && dateCal.get(Calendar.DAY_OF_MONTH) >= 7
&& dateCal.get(Calendar.DAY_OF_MONTH) <= 14 && timeCal.get(Calendar.HOUR_OF_DAY) >= 3) {
zoneOffset -= TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS);
}
} else if (dateCal.get(Calendar.MONTH) == Calendar.NOVEMBER) {
if (Calendar.SUNDAY == dateCal.get(Calendar.DAY_OF_WEEK) && dateCal.get(Calendar.DAY_OF_MONTH) <= 7
&& timeCal.get(Calendar.HOUR_OF_DAY) >= 3) {
zoneOffset += TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS);
}
}
long timeMs = timeCal.getTimeInMillis() + zoneOffset + timeCal.get(Calendar.DST_OFFSET);
return addMillisecondsToDate(date, timeMs);
}
}
我不喜欢这个方法,因为如果DST的规则会改变,那么这个方法将需要更新。是否有可以执行类似功能的库?
I'm not fond of this method because if the rules for DST ever change then this method will need to be updated. Is there a library that would perform a similar function ?
这篇关于将GregorianCalendar转换为DST当天的日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!