Java中的Date类在表示1900-01-01 08:05:43之前的时间数据时出现偏差

        我发现Java中的Date类在1900-01-01 08:00:00之前的时间数据在使用SimpleDateFormat进行格式化与解析是出现了5分43秒的偏差。

1、发现过程

        想用Java实现根据数据库表名称将Excel表格中的数据导入到该表中的功能,就类似于Navicat通过Excel导入数据的功能。

        首先我用DBeaver将表数据导出为CSV文件,然后将文件另存为Excel格式,mysql中time类型的数据会被存储为时间格式(使用Navicat导出Excel的话会被存储为常规字符串)。

        将Excel文件使用POI读取到Java代码中,对时间格式的时间进行解析读取,会将time类型的数据读取为Date,从而包含年月日时分秒的数据。

        例如:数据库中存储的是 “00:00:00” ,读取格式化之后就会变为“1899-12-31 00:00:00”。

        因为MySQL的time类型允许小时部分大于24(测试了下最大可以输入到838:59:59),如果直接取Date的时分秒部分显然是不对的,我的想法是 “用每次读取到的date的毫秒值-1899-12-31 00:00:00的毫秒值 = 实际的数据的毫秒值, 然后经过计算就能得到对应的时分秒。

        按照上述想法计算完成进行测试时,发现部分比较的数据导入到数据库之后时间少了5分43秒,于是做了以下几个测试案例,发现确实有一部分数据有偏差。

2、测试案例

2.1案例一

        利用格式化字符串解析为Date数据,获取Date的毫秒值,并将Date数据在格式化为字符串;

        以下四个数据都是边界值:

        当时间大于1900-01-01 08:05:42相互转换都一切正常;

        当时间小于等于1900-01-01 08:05:42,大于等于1900-01-01 08:00:00 时,解析出的时间比字符串数据大343000毫秒,再次格式化正常,现象就是格式化比原始时间大了5分43秒。

        当时间小于1900-01-01 08:00:00,解析出的时间毫秒值比字符串数据大了343000毫秒,但是再次格式化的字符串又与原始时间一致。

        解析的时间毫秒值是否正确可以找任意的在线转换工具进行验证。

@Test
    public void test1() throws ParseException {


        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String teststr1 = "1900-01-01 08:05:43";
        String teststr2 = "1900-01-01 08:05:42";
        String teststr3 = "1900-01-01 08:00:00";
        String teststr4 = "1900-01-01 07:59:59";
        List<String> list = Arrays.asList(teststr1, teststr2, teststr3, teststr4);

        for (String s : list) {
            Date parse = sdf.parse(s);
            String format = sdf.format(parse);
            System.out.println("--------------------------");
            System.out.println("原始时间:  " + s);
            System.out.println("时间戳:   " + parse.getTime());
            System.out.println("格式化时间:" + format);
        }
    }

执行结果:

2.2 案例二

        在网上找时间戳在线转换工具,找出了五个时间的毫秒值,将这些毫秒值转为Date并进行格式化。

        执行的结果发现:

        当时间大于1900-01-01 08:05:42的时候一切正常;

        当时间小于等于1900-01-01 08:05:42的时候,格式化出的时间字符串始终小5分43秒。

        将毫秒值转为Date的时候Date所表示的值已经变小了。

@Test
    public void test2() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        long time0 = 567993942000l; // 1988-01-01 08:05:42
        long time1 = -2208988800000l; // 1900-01-01 08:05:43
        long time2 = -2208988801000l; // 1900-01-01 08:05:42
        long time3 = -2208989143000l; // 1900-01-01 08:00:00
        long time4 = -2208989144000l; // 1900-01-01 07:59:59
        long time5 = -2240553943000l; // 1899-01-01 00:00:00
        List<Long> longs = Arrays.asList(time0, time1, time2, time3, time4, time5);

        for (Long aLong : longs) {
            Date date = new Date(aLong);
            System.out.println("--------------------------");
            System.out.println("原始时间戳: " + aLong);
            String format = sdf.format(date);
            System.out.println("格式化时间:" + format);

        }
    }

执行结果:

3、总结

        以上是发现的问题以及案例描述,我不太清楚为什么会出现这样的现象,只是碰巧遇到了这个问题,希望看到的大佬能够解答一下出现这个现象的原因,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值