`
agapple
  • 浏览: 1583753 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java Date.getTime()返回负数异常情况分析

 
阅读更多

背景

  在线上运行的一个数据库同步系统,突然在某一天发现了一条奇怪的数据。 出现了如下异常:

 

SQL state [99999]; error code [17361]; Year out of range.; nested exception is java.sql.SQLException: Year out of range.:

 

 分析其对应的数据内容,就发现了有一个Oracle的Date类型的数据字段,返回了-235316004988000L. 

 

EventColumn[index=0,columnType=93,columnName=RESERVED_TIME,columnValue=-235347540988000,oldColumnValue=<null>,isNull=false,isKey=false],

过程

1. 查询了下数据库源库中的数据记录(oracle 11g)

 

 

RESERVED_TIME           TO_CHAR(RESERVED_TIME,'YYYY-MM-DDHH24: 
-------------------             --------------------------------------
5488-04-02 11:03:32   0000-00-00 00:00:00   

 

注意: oracle to_char函数出现失败. 

 

2. 接着dump了下"5488-04-02 11:03:32"的记录和对应该异常数据的记录,发现16进制下数据有点不同

 

dump(RESERVED_TIME,16): 

5488-04-02 11:03:32
Typ=12 Len=7: 2d,70,4,2,c,4,21

5488-04-02 11:03:32
Typ=12 Len=7: 9a,bc,4,2,c,4,21

 

3. 通过jdbc获取数据库返回结果数据

    出现了本文的重点: Timestamp.getTime() =  -253402271999000

原因

做java的人,基本都知道Date.getTime()返回的时间是相对于"1970-01-01 00:00:00"的毫秒数差值。

对应的javadoc说明:


 

思考: 那1969年的Date对象,获取到的getTime会是一个什么结果? 

测试1: (1970年边界值测试)

 

public static void test_1970() throws Exception {
        TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
        Date date1 = parse("1970-01-01 00:00:00"); // 0值
        Date date2 = parse("1969-12-31 00:00:00"); // -86400000值
        System.out.printf("1970 date:%s ,1969 date: %s \n", date1.getTime(), date2.getTime());
    }

 

结果很明显,返回的是负数

测试2:(0000年边界值测试)

 

public static void test_zero() throws Exception {
        TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
        Date date1 = parse("0001-01-01 00:00:00");
        long time = date1.getTime();
        Date date2 = new Date(time - ONE_DAY); // 获取公元1年的下一天
        System.out.printf("date:%s \n", format(date2)); // 0001-12-31 00:00:00, 做了一个轮回

        Date date3 = new Date(time - ONE_DAY * (365 + 1)); // 获取公元1年的下一年
        System.out.printf("date:%s \n", format(date3)); // 0001-01-01 00:00:00 , 做了一个轮回,公元前1年
    }

 

结果:

 

  • 0001-01-01的下一天是,0001-12-31 (一个轮回)
  • 0001-01-01的下一年是, 0001-01-01 (一个年的轮回)
测试3:(本文的异常数据)

获取正常的5488年的time数据

 

Date test = parse("5488-04-02 11:03:32");
System.out.printf("time:%s \n", test.getTime()); // 输出111025307012000 

计算一下:

 

public static void test_answer() throws Exception {
        Date test = parse("5488-04-02 11:03:32");
        Date zero = parse("0001-01-01 00:00:00");

        long days = (test.getTime() - zero.getTime()) / ONE_DAY;
        long ans = (111025307012000L - (-235316004988000L)) / ONE_DAY - days;

        Date now = new Date(zero.getTime() - ONE_DAY * (ans + 1)); // 获取公元1年的下一年
        System.out.printf("date:%s \n", format(now)); // 5488-04-01 00:00:00 , 做了一个轮回
    }
结果: 
  • 111025307012000代表的是正确的5488年的time类型
  • -253402271999000代表的是从0001再往前倒数5000多年的数据,也就是说是公元前5488年的意思。

结论

 

  1. 1970年的前一天的getTime返回的是-1 * 24 * 3600 * 1000 = -86400000
  2. 0001年的前一年(公元前1年),java里表示还是0001年
所以本文里的两个time时间:111025307012000 , -253402271999000都是代表着"5488-04-02 11:03:32",只不过前者是公元,后者是公元前的区别,问题就已经很明确了。

 

  • 大小: 14 KB
分享到:
评论

相关推荐

    JAVA new Date()或Calendar.getInstance().getTime()得到的时间不对

    NULL 博文链接:https://ollevere.iteye.com/blog/1320854

    Java Date Time教程-java.util.Date

    Java的java.util.Date类是Java初的时间类之一。该类的大部分方法已不推荐使用,取而代之的...  你可以通过getTime()方法访问java.util.Date实例的日期和时间,比如像这样:  java.util.Date date = new java.util.D

    javascript 倒计时

    var nMS =EndTime.getTime() - NowTime.getTime();//getTime()方法将日期转为毫秒数;1秒=1000毫秒 var senconds=1000; var minutes=senconds*60; var hours=minutes*60; var days=hours*24; var nD =Math.floor(nMS...

    个人网站的素材

    sd = new java.sql.Date(ud.getTime());2、如果要插入到数据库并且相应的字段为Date类型那么可以用PreparedStatement.setDate(int ,java.sql.Date)方法其中的java.sql.Date可以用上面的方法得到也可以用数据库提供...

    java DATE与时间戳互化

    java_时间戳与Date_相互转化 (2012-02-10 17:54:49) 转载▼ 标签: java 时间戳 date 转换 转化 杂谈 分类: java 1、时间戳的定义  时间戳是指文件属性里的创建、修改、访问时间。 数字时间戳技术是数字签名...

    判断2个时间大小

    if (date2.getTime()&lt;date1.getTime()){ i= 1; }else if (date2.getTime()==date1.getTime()){ i= 2; }else if (date2.getTime()&gt;date1.getTime()){ //正常情况下的逻辑操作. i= 3; } } catch (Parse...

    warped-time:s提供与Date.getTime()等效的选项,具有可变的进度速度和可选的服务器时间同步

    扭曲时间:控制时间的进度 :play_button: | | | 简单的Javascript库,提供与Date.getTime()等效的变量,并且具有可变的进度速度。 它有一个钩子来接收时间戳和估计的延迟,用于与后端服务器的时间保持同步。yarn add...

    DateUtils.java 日期处理相关工具类

    import java.util.Date; import java.util.TimeZone; /** * 文件名:DateUtils.java 日期处理相关工具类 * 版本信息:V1.0 * 日期:2013-03-11 * Copyright BDVCD Corporation 2013 * 版权所有 ...

    javascript 元旦倒计时的代码

    var yd_time = yd_date.getTime(); var one_second = 1000; var one_minute = one_second * 60; var one_hour = one_minute * 60; var one_day = one_hour * 24; getRemainTime(); function getRemainTime...

    新软件库和调用QQ登录IAPP源码已修复报错

    java(stamp,date,”java.util.Date.getTime”) s(stamp/1000,ss.times) //毫秒级变成秒级 ss(ss.times+”yuqios”,ss.timemd5) call(ss.timemd5, “mjava”, “md5.md5st”,ss.timemd5) end fn 源码纯净无后,放心...

    Android GPS时间转本地时间

    android gps开发获取的时间“location.getTime()”,转换为本地北京时间的代码,经测试绝对好用。

    jQuery实现强制cookie过期方法汇总

    date.setTime(date.getTime() + (x * 60 * 1000)); $.cookie('example', 'foo', { expires: date }); 方法二: [removed] var expiresDate= new Date(); expiresDate.setTime(expire.getTime() + (? * 60 * 1000))...

    时间格式化

    import java.util.Date; /** * 日期时间类 * Created by hssboy on 2016/10/15. */ public class DateUtil { public static Date getDate() { return new Date(); } /** * 时间戳(14123244334) * * @...

    vue element ui 时间选择器设置

    return time.getTime() Date.now(); } }, pickerOptions1: { disabledDate: time =&gt; { // 使用2018年的毫秒时间戳判断 return time.getTime() Date.now(); } } } } 在发送请求之前进行日期的判断,

    xfire测试项目(包括复杂数据类型)

    public java.util.Date getUDate(java.util.Date a); public java.util.Calendar getCalendar(java.util.Calendar a); public java.sql.Timestamp getTimestamp(java.sql.Timestamp a); public java.sql.Date ...

    JavaScript中的getTime()方法使用详解

    javascript Date.getTime()方法按照通用时间对应的时间为指定日期返回数值。由getTime方法返回的值是毫秒自1970年1月1日00:00:00的数。 您可以使用此方法来帮助指定日期和时间到另一个Date对象。 语法 Date.getTime...

    nodejs如何获取时间戳与时间差

     2.Date.now()  3.process.uptime()  4.process.hrtime() 平时想获取一个时间戳的话,用这些方法都可以,那么这些方法有什么区别呢? new Date().getTime()和Date.now() 这些方法是通过node运行环境的系统...

    Java 实现判断今天是工作日、假日、节假日.zip

    Java 实现判断今天是工作日、假日、节假日。 其中有两个方法,一个方法是: /** * 获取今天日期值 */ public Date getCurrentDate() { return Calendar.getInstance().getTime(); } 另一个方法是: /** * ...

    java时间处理工具类--CalendarUtil(java源码)

    now.set(Calendar.DATE, now.get(Calendar.DATE) - 1); now.set(Calendar.HOUR, 11); now.set(Calendar.MINUTE, 59); now.set(Calendar.SECOND, 59); return now.getTime(); } /** * 获得所在月份的...

    计算工作日

    if(holidayArray[i].getTime()&gt;orgTime && holidayArray[i].getTime()&lt;to.getTime()){ if(holidayArray[i].getDay()&gt;0 && holidayArray[i].getDay()){ workdays--; } } } } return workdays; } [removed]

Global site tag (gtag.js) - Google Analytics