在实际的项目中,时间是非常常见的一种应用,因此一般为时间格式化创建一个工具类,用于将项目中的时间进行格式化,目前使用的是
SimpleDateFormat
,但是在阿里编码规范检查中有一项检查,此项检查中不推荐使用
SimpleDateFormat
,因此本文对此项检查进行分析,用于设计出一个比较好用的时间格式化工具类。
检查条目描述如下:
SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 说明:如果是JDK8的应用,可以使用instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。
-
使用SimpleDateFormat 进行格式当前时间代码如下
public static String formatCurrent(String format){
SimpleDateFormat df = new SimpleDateFormat(format, Locale.US);
return df.format(new Date());
- 使用DateTimeFormatter进行格式化代码如下
public static String formatCurrent(String format){
LocalDateTime dt = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return formatter.format(dt);
小结
从格式化当前的功能来看,代码量差不多,易用性也差不多,同时 DateTimeFormatter 是线程安全的,确实带来了好处。
国际化问题
以月份为例子,其他例如星期,上午下午,等在国际化的时候都会受到影响
public static String formatCurrent(String format){
SimpleDateFormat df = new SimpleDateFormat(format, Locale.CHINA);
return df.format(new Date());
public static String formatCurrent(String format){
SimpleDateFormat df = new SimpleDateFormat(format, Locale.US);
return df.format(new Date());
- 使用SimpleDateFormat 进行格式化时间进行转换,代码如下
public static String transformTime(String time, String oldFormat, String newFormat) {
try {
return new SimpleDateFormat(newFormat).format(new SimpleDateFormat(oldFormat).parse(time));
} catch (Exception e) {
e.printStackTrace();
return time;
- 使用DateTimeFormatter进行格式化时间进行转换,代码如下
public static String transformTime(String timeStr,String oldFormat,String newFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(oldFormat);
LocalDateTime dt = LocalDateTime.parse(timeStr, formatter);
return DateTimeFormatter.ofPattern(newFormat).format(dt);
使用DateTimeFormatter需要注意的问题是有:
- 如果带有毫秒,且格式为
yyyyMMddHHmmssSSS
,会抛出异常,调用代码如下。bug 描述。在java9 应该已经解决这个问题,但是目前android 还不支持java9,在android 上面还存在这个问题。
String newRet1 = NewDateUtils.transformTime("20200630163030123","yyyyMMddHHmmssSSS","yyyy-MM-dd HH:mm:ss:SSS");
* 抛出异常 java.time.format.DateTimeParseException: Text '20200630163030123' could not be parsed at index 0
public static String transformTimeMil(String timeStr,String oldFormat,String newFormat) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyyMMddHHmmss")
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter();
LocalDateTime dt = LocalDateTime.parse(timeStr, formatter);
return DateTimeFormatter.ofPattern(newFormat).format(dt);
- 格式化年月日时分秒使用LocalDateTime,格式化年月日,使用LocalDate,格式化时间(时分秒)使用LocalTime。不能统一使用LocalDateTime进行格式化
代码如下
public static String transformTime(String timeStr,String oldFormat,String newFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(oldFormat);
LocalDateTime dt = LocalDateTime.parse(timeStr, formatter);
return DateTimeFormatter.ofPattern(newFormat).format(dt);
String newRet1 = NewDateUtils.transformTime("20200630", "yyyyMMdd","yyyy-MM-dd");
- LocalDate 无法只格式化月和日,代码如下
public static String transformDate(String timeStr,String oldFormat,String newFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(oldFormat);
LocalDate dt = LocalDate.parse(timeStr, formatter);
return DateTimeFormatter.ofPattern(newFormat).format(dt);
String newRet1 = NewDateUtils.transformDate("0630", "MMdd","MM-dd");
String newRet1 = NewDateUtils.transformDate("202006", "yyyyMM","yyyy-MM");
小结
从格式化时间转换这个功能来说,DateTimeFormatter 的设计并不完美,或者因为本人知识有限,使用方式不对,造成的问题。从格式化时间转换这个功能点来说,DateTimeFormatter 在android 上面尚不具备在项目中编写成工具类的条件。
- 使用SimpleDateFormat 判断时间是否有效
public static boolean isValidDate(String str, String pattern) {
SimpleDateFormat format = new SimpleDateFormat(pattern);
try {
format.setLenient(false);
format.parse(str);
}catch (ParseException e) {
e.printStackTrace();
return false;
return true;
- 使用 DateTimeFormatter 来判断时间的有效性。
ret = NewDateUtils.isValidDate("20200630","uuuuMMdd");
public static boolean isValidDate(String str, String pattern){
try {
DateTimeFormatter.ofPattern(pattern)
.withResolverStyle(ResolverStyle.STRICT)
.parse(str);
} catch (RuntimeException e) {
e.printStackTrace();
return false;
return true;
当然,时间格式的使用还有判断时间的大小,计算出距离某个时间前或者后的时间等等。从第二点(格式化时间转换)来看,目前DateTimeFormatter 还不具备足够大的优势,替换SimpleDateFormat。SimpleDateFormat 面临的问题就是线程安全的问题,定义为工具类,且SimpleDateFormat 为局部变量,可以解决线程安全的问题,但是导致的问就是SimpleDateFormat为局部变量,创建了大量的实例,消耗了空间。同时了解到有一个开源库Joda-Time
对时间的操作比较友好,但是目前暂时没有进行体验,后面有时候可以深度体验一下。
阿里编码规范检查在阿里编码规范检查中有一项检查是java8推荐使用检查条目描述如下:SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 说明:如果是JDK8的应用,可以使用instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable
在 Android 中,可以使用 java.text.DateFormat 类来格式化时间。 例如,要将当前时间格式化为中国的默认格式(类似于 "2022年12月29日 星期四 下午3点45分56秒"),可以使用以下代码:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale....
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
dateTimeFormatter.format(LocalDateTime.now());
SimpleDateFormat sim
在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗
通过阅读本篇文章你将了解到:
为什么需要LocalDate、LocalTime、LocalDateTime【java8新提供的类】
java8新的时间API的使用方式,包括创建、格式化、解析、计算、修改
为什么需要LocalDate、LocalTime、LocalDateTime
Date如果不格式化,打印出的日期可读性差
Tue Sep 10 09:34:04 CST 201
获得当前时间的本周一的凌晨零点零分零秒的时间,时间戳。
获得当前时间的本月的第一天的凌晨零点零分零秒的时间,时间戳。
新接口更好用的原因是考虑到了日期时间的操作,经常发生往前推或往后推几天的情况。
使用Java 8 新提供的API可以很好的操作时间。
时间和日期,可以实现简单的加plus 减 minus。可以操作的跨度:...
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Loca
1、把格式化好的字符串解析成时间对象
Joda-Time为这两个核心需求的解决方案就是DateTimeFormatter。
额外提一点,DateTimeFormatter在格式化和解析时是支持时区的。
二、核心对象:
2.1 DateTimeFormatter
日期格式化与解析
2.2 LocalD...
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
* @author xiaobu
* @version JDK1.8.0_171
* @date on 2019/...