SimpleDateFormat 是一个各种项目中使用频度都很高的类,主要用于时间解析与格式化,频繁使用的主要方法有parse和format.
parse方法:将字符串类型(java.lang.String)解析为日期类型(java.util.Date)
format方法:将日期类型(Date)数据格式化为字符串(String)
因为用的很多,所以在使用的时候需要关注更多细节,才能避免更多的坑。(踩得坑多了,才能成为一个会填坑的程序员。)
1. SimpleDateFormat是线程不安全的
官方文档解释如下(参见SimpleDateFormat):
Synchronization
Date formats are not synchronized. It is recommended to create separate format instances for each thread.
If multiple threads access a format concurrently, it must be synchronized externally.
Date formats 是线程不安全的。推荐为每个线程创建单独的format实例。如果多线程并发访问同一个format实例,必须加同步操作。
错误的实现(前提是DateUtils.parseString()方法被多线程调用)
public class DateUtils {
public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
// incorrect while be called by multiple threads
public Date parseString(String datetime) throws Exception {
return format.parse(datetime);
}
}
正确实现:
class DateUtils {
public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private static final Object LOCK = new Object();
// OK
public Date parseString(String datetime) throws Exception {
synchronized (LOCK) {
return format.parse(datetime);
}
}
// OK
public Date parseStringV2(String datetime) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
return format.parse(datetime);
}
}
2.SimpleDateFormat解析异常java.text.ParseException: Unparseable date
这个问题在stackoverflow上大概出现了1000+,在很多时候程序使用SimpleDateFormat都能正常执行,并不会报错;但有时发现日志出现
java.text.ParseException: Unparseable date: “2017-03-20 02:10″异常,为什么还抛出这种异常呢?
先来看看代码:
public Date parseStringV2(String datetime) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.parse(datetime);
}
可以看到输入时间为:2017-03-20 02:10, 解析的格式为:yyyy-MM-dd HH:mm:ss.
经过测试发现,当使用format方法将Date转成String时,SimpleDateFormat可实例化为任意期望的时间格式;但是使用parse方法将String转为Date时,SimpleDateFormat定义的格式与参数String的格式必须完全一致,不然就会出现Unparseable date。
另外,当使用Restful api服务时,后端Server与前端APP系统语言(本地环境)存在差异,也有可能出现“输入时间为:2017-03-20 02:10, 解析的格式为:yyyy-MM-dd HH:mm,格式完全一致,parse偶尔也会解析出错”,因为存在偶然不确定行,解决方案还持续分析中。