0

我在我们现有的应用程序中面临一个问题,其中员工输入的时间(从他的组织/商店使用时钟应用程序)首先转换为 GMT,然后存储在数据库中。并且为了显示回来,将GMT时间转换回存储本地时区并显示。在大多数情况下,这可以正常工作,但当时区移动到 DST 时则不行,反之亦然。

让我更具体一点。假设商店的标准时区是 GMT-8 并且员工在早上 08:00 打卡,因此将时间转换为 GMT 16:00,然后存储在 DB 中。转换过程首先将这个 08:00 AM 转换为存储本地时间,以某种方式给出 17:00 CET,然后这个 17:00 CET 转换为 GMT,给出 16:00 CET。

但是,如果我们以 3 月 31 日的 DST 为例,此时 02:00 AM 变为 03:00 AM。假设员工在 18:00(3 月 30 日)打卡,它在第一次转换为本地时返回给我 04:00 AM CEST,然后当我将其转换为 GMT 时,它给出了 03:00 CEST。因此,在将其转换回来时,这会给出 19:00,这是不正确的。该设计表示本地时间被转换为 UTC,然后存储在数据库中,但如果它仍然是 UTC,那么它应该存储 02:00 AM 而不是 03:00 AM,因为 GMT/UTC 没有 DST。

用于进行转换的代码是:

步骤1

final Date localPunchDateTime = R3ValConverter.convertFromTimeZone(teData.m_dtTm,  
                                               TimeZone.getTimeZone("GMT-8"));

第2步

teData.m_dtTm = R3ValConverter.convertToGMT( localPunchDateTime );

R3ValConverter.java

public static Date convertFromTimeZone(final Date dtSrc, final TimeZone tzSrc)
    {

        final SISDateTime dtTmTemp = new SISDateTime(dtSrc, TimeZone.getDefault());
        final SISDateTime dtTmSrc = new SISDateTime( dtTmTemp.getYear(), dtTmTemp.getMonth(), 
                                                     dtTmTemp.getDate(), dtTmTemp.getHour(), 
                                                     dtTmTemp.getMinute(), dtTmTemp.getSecond(), 
                                                     tzSrc );

        return dtTmSrc.toDate();                                                       
    }

SISDateTime

GregorianCalendar m_cal;

public SISDateTime(Date dt, TimeZone tz) throws SISDateTimeException
    {

        m_cal = new GregorianCalendar(tz);
        m_cal.setTime(dt);
        resetMillis();
    }

另一个 SISDateTime 方法也使用相同的 GregorianCalendar。

我真的很感激在这方面的任何帮助。我在这里假设我们在第一步中遇到了一些问题,但目前不知道有什么好的解决方案。

4

1 回答 1

0

您必须在数据库中存储从本地时间到 UTC 的 UTC + 当前偏移量(以秒为单位)。所以如果你想保留本地时间,你总是需要一对 (Utc time, offset)

然后使用TimezoneWithOffsetFromGMT(或类似名称)

于 2013-04-18T08:01:13.073 回答