1. 问题的发现
- 使用如下方法进行转换,发现日期转换前后居然相差了
5
天!!!
System.out.println(transferString2Date("1000-01-01").toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
2.运行结果为:
1000-01-06
3.其中,transferString2Date
方法如下
public static Date transferString2Date(String s) { Date date = new Date(); try { date = new SimpleDateFormat("yyyy-MM-dd").parse(s); } catch (ParseException e) { e.printStackTrace(); } return date; }
- 这种情况发生在项目中是没有任何报错的,不会抛出任何异常,只能在人工发现数据异常后去慢慢排查,实在是太可恶了!!!那么为什么会出现这种错误呢?
2. 问题的排查
- 首先排查
transferString2Date
方法的问题,发现该方法的输出为
Mon Jan 01 00:00:00 CST 1000
- 因此这个方法没有问题。
- 然后排查
toInstant
方法,点进该方法
/** * Converts this {@code Date} object to an {@code Instant}. * <p> * The conversion creates an {@code Instant} that represents the same * point on the time-line as this {@code Date}. * * @return an instant representing the same point on the time-line as * this {@code Date} object * @since 1.8 */ public Instant toInstant() { return Instant.ofEpochMilli(getTime()); }
3.继续点进getTime
方法,问题来了
/** * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT * represented by this <tt>Date</tt> object. * * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT * represented by this date. */ public long getTime() { return getTimeImpl(); }
该方法返回一个从1970-01-01 00:00:00
起到该时间的毫秒数!!!而我传入的时间是要早于1970-01-01 00:00:00
的,因此会产生问题。
3. 问题的解决
1.已经发现了问题的所在,那么要如何解决这一问题呢?
2.在实际开发中,很少会遇到1970-01-01 00:00:00以前的时间。在我的这次开发任务中,业务方提供的数据中使用了1000-01-01来标识该字段时间是一个无效时间。因此对于这类场景的最优解其实是,使用与日期无关的类型,比如notUpdated而不是1000-01-01来表示无效时间。