去除中国夏令时对日期的影响

背景

夏令时(Daylight Saving Time),又称日光节约时间。通过将时钟往前调一个小时,从而让人早睡早起,节约使用灯光。
在我国曾经在一段时间内使用过夏令时,在编程时会导致一些问题。比如我们在计算生日的时候,从数据库中取得日期信息一般是不会带上时区信息的。在数据库中存储的形式是:1986-05-05 00:00:00,而通过JDBC读取的时候就会变成这样的形式:1986-05-05 00:00:00 +0900。
这个的时间转换为东八区时间之后,会发生这样的问题,生日提前了一天,变成了:1986-05-04 23:00:00 +0800。
接下来提供一种解决方案,去除从字符串或者是数据库中读取的夏令时日期,会少一个小时的问题。

解决方案

通过Calendar得到Date中DST的偏移量,并且将偏移量加入到Date中,并且对夏令时第一天进行特殊判断,因为在夏令时第一天的开始是从凌晨一点开始的,比如1986-05-03 23:59:59 +0800的下一秒就是1986-05-04 01:00:00 +0900。

public static Date removeChineseDst(Date originDate) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(originDate);
    int dstOffset = calendar.get(Calendar.DST_OFFSET);
    int month = calendar.get(Calendar.MONTH);

    if (dstOffset > 0 && 3 <= month && month <= 4) {
        calendar.add(Calendar.HOUR_OF_DAY, -1);
        if (calendar.get(Calendar.DST_OFFSET) == 0) {
            return originDate;
        }
        calendar.add(Calendar.HOUR_OF_DAY, 1);
    }
    calendar.add(Calendar.MILLISECOND, dstOffset);
    return calendar.getTime();
}

测试代码如下

package com.johnson.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Test;

public class DateUtilTest {
    @Test
    public void test_removeChinaDst() throws ParseException {
        SimpleDateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = formatter.parse("1986-05-04 00:00:00");
        System.out.println(outputFormatter.format(date));

        date = DateUtil.removeChineseDst(date);
        System.out.println(outputFormatter.format(date));

        date = formatter.parse("1986-05-05 00:00:00");
        System.out.println(outputFormatter.format(date));
        date = DateUtil.removeChineseDst(date);
        System.out.println(outputFormatter.format(date));
    }
}

扩展

中国时区知识

中国使用的时区是Asia/Shanghai,这个时区在1901-1927年采用的是上海地方时,比东八区标准时快了5分55秒。

中国夏令时区间

年份时间区间
198605-04~09-14
198704-12~09-12
198804-10~09-10
198904-16~09-16
199004-15~09-15
199104-14~09-14
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值