将GregorianCalendar转换为DST当天的日期? [英] Converting GregorianCalendar to Date on day of DST loses an hour?

查看:129
本文介绍了将GregorianCalendar转换为DST当天的日期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在解决将仅代表当前日期(即,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆