记java.text.SimpleDateFormat转换yyyyMMdd格式时显示错误的问题
场景:
项目中保存用户身份证有效期的字段存储格式为yyyyMMdd,而使用第三方OCR解析包也并不能保证100%的正确率,所有我们需要校验下格式是否有误。
如:用户实际过期时间为20220530,但因照片有些模糊就解析成20200538了。
准备工作:
准备好工具类,有如下几个函数:
1 public static String dateToString(Date date, String formate) { 2 if (date == null) { 3 return ""; 4 } 5 DateFormat dateFormat = new SimpleDateFormat(formate); 6 return dateFormat.format(date); 7 } 8 9 public static Date string2date(String dateString, String formatStr) { 10 Date formateDate = null; 11 DateFormat format = new SimpleDateFormat(formatStr); 12 try { 13 formateDate = format.parse(dateString); 14 } catch (ParseException e) { 15 return null; 16 } 17 return formateDate; 18 } 19 20 /** 21 * 将字符类型的日期转换输出形式 22 * 如:20190101 >>> 2019-01-01; value=20190101, form=yyyyMMdd, to=yyyy-MM-dd 23 * 24 * @param value 待转换的值 25 * @param from 原字符日期输出格式 26 * @param to 转换后的日期输出格式 27 * @return 28 */ 29 public static String string2string(String value, String from, String to) { 30 return dateToString(string2date(value, from), to); 31 } 32 33 /** 34 * 校验yyyyMMdd格式的日期是否正确 35 * <p> 36 * 因new SimpleDateFormat(format).parse(dateStr)在转换错误的yyyyMMdd格式时并不会抛出ParseException,所以需要另作处理: 37 * 1、首先将yyyyMMdd转换成yyyy-MM-dd格式(此时不会抛出异常,但会显示与之前不一样的时间) 38 * 2、将第一步转换后得出的时间与源时间进行比较,相同则为正确格式的日期,不同则为错误格式的日期 39 * <p> 40 * 如:source = "20200835" 41 * 1、format = "2019-12-08" 42 * 2、replace = "20191208" 43 * 3、source.equals(replace) = false 44 * 45 * @param source 日期源 46 * @return true-格式正确,false-格式错误 47 */ 48 public static boolean verify_yyyyMMdd(String source) { 49 String format = string2string(source, DateFormatUtil.YYYYMMDD, DateFormatUtil.YYYY_MM_DD); 50 String replace = format.replace("-", ""); 51 return source.equals(replace); 52 }
遇到的坑:
使用java.text.SimpleDateFormat转换yyyyMMdd格式时会转换成预期之外的时间,如20200835会转换成20191208(上述代码的注释)。
解决方案:
因为我不能改变第三方OCR的解析,所有我就需要在OCR解析到错误的值时让用户重新发起,所以我这里做的也只是对日期的校验。
方案如下(同样的注释也说得很清楚):
- 首先将yyyyMMdd转换成yyyy-MM-dd格式(此时不会抛出异常,但会显示与之前不一样的时间)
- 将第一步转换后得出的时间与源时间进行比较,相同则为正确格式的日期,不同则为错误格式的日期
1 boolean identityStartVerify = DateFormatUtil.verify_yyyyMMdd(customer.getIdentityStart()); 2 boolean identityExpiresVerify = DateFormatUtil.verify_yyyyMMdd(customer.getIdentityExpires()); 3 if (!identityStartVerify || !identityExpiresVerify) { 4 logger.info("{} 身份证格式有误,identityStartVerify={} identityExpiresVerify={}", orderId, 5 identityStartVerify, identityExpiresVerify); 6 return Response.fail("身份证格式有误"); 7 }