欢迎关注微信公众号: 程序员小圈圈
原文首发于: www.zhangruibin.com
本文出自于: RebornChang的博客
转载请标明出处^_^
在看阿里开发规范手册时,看到了这点:
【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(“yyyy-MM-dd”);
}
};
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。
上面提到了两个知识点,Instant和LocalDateTime以及DateTimeFormatter。
细想之下之前对这个小知识还真的忽略了,所以来说下各个的用法。
通过查看源码我们可以看到,Instant implements Temporal, TemporalAdjuster, Comparable, Serializable
注释上写着:This class is immutable and thread-safe.也就是线程安全。
简单的来说, Instant 类代表的是某个时间(有点像 java.util.Date),它是精确到纳秒的(而不是象旧版本的Date精确到毫秒)。如果使用纳秒去表示一个时间则原来使用一位Long类型是不够的,需要占用更多一点的存储空间,实际上其内部是由两个Long字段组成,第一个部分保存的是自标准Java计算时代(就是1970年1月1日开始)到现在的秒数,第二部分保存的是纳秒数(永远不会超过999,999,999)。
那么怎么使用呢?
看下面:
Instant instantNow = Instant.now();
System.out.println("now:"+instantNow);
上面我们可以看到,直接now出来的时间和我们现在的北京时间也就是东八区时间有出入,看下源码注释,调用这个now()会查询一个system UTC clock,也就是:
Clock clock = Clock.systemUTC();
也就是说,如果你在中国的话,得到的不是中国(东八区)时间,那怎么才是中国时间呢?加八个小时就是北京时间:
Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
那怎么获得1970-01-01T00:00:00Z.到现在的秒数及毫秒数呢?
System.out.println("秒数:"+now.getEpochSecond());
System.out.println("毫秒数:"+now.toEpochMilli());
如果说上面的instant是需要手动增加时间来确定自己的时区时间,那么LocalDateTime就不需要增加时间,使用方法与instant是有相似之处的:
LocalDateTime localDateTime = LocalDateTime.now();
而且还可以进行比较,转化等操作,如下:
LocalDateTime localDateTime = LocalDateTime.now();
//当前时间
System.out.println("localDateTime:"+localDateTime);
//format时间
System.out.println("localDateTimeFormat:"+localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//定义localDateTime LocalDateTime localDateTime = LocalDateTime.now();
LocalDate now1 = LocalDate.now();
LocalTime now2 = LocalTime.now();
System.out.println("localDateTime:"+localDateTime);
System.out.println("now1:"+now1);
System.out.println("now2:"+now2);
System.out.println("localDateTimeFormat:"+localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//定义localDateTime2 LocalDateTime localDateTime2 = localDateTime.minus(23, ChronoUnit.MONTHS);
localDateTime.atZone(ZoneId.systemDefault());
localDateTime2 = localDateTime2.withHour(3);
localDateTime2 = localDateTime2.withYear(2019);
localDateTime2 = localDateTime2.with(ChronoField.MONTH_OF_YEAR,3);
System.out.println("localDateTime2:"+localDateTime2);
//比较两个时间 Duration duration = Duration.between(localDateTime,localDateTime2);
System.out.println("比较日:"+duration.toDays());
System.out.println("比较时:"+duration.toHours());
System.out.println("比较分:"+duration.toMinutes());
Period period = Period.between(localDateTime.toLocalDate(),localDateTime2.toLocalDate());
System.out.println("比较年:"+period.getYears());
System.out.println("比较月:"+period.getMonths());
System.out.println("比较日:"+period.getDays());
//互相转化 Date date = Date.from(localDateTime2.atZone(ZoneId.systemDefault()).toInstant());
LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault());
localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
稍微提下LocalDate及LocalTime,这两个欠着是不带具体的时分秒只有年月日,后者是不带具体的年月日只有时分秒。
强力的时间类型模式化工具,有多强呢?
看看下面:
//定义新的时间 LocalDateTime newTime = LocalDateTime.now();
//定义多种格式化类型 DateTimeFormatter[] formatters = new DateTimeFormatter[]{
// 直接使用常量创建DateTimeFormatter格式器
//第1种 DateTimeFormatter.ISO_LOCAL_DATE,
//第2种
DateTimeFormatter.ISO_LOCAL_TIME,
//第3种
DateTimeFormatter.ISO_LOCAL_DATE_TIME,
//第4种
// 使用本地化的不同风格来创建DateTimeFormatter格式器 DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM),
//第5种
DateTimeFormatter.ofLocalizedTime(FormatStyle.LONG),
//第6种
// 根据模式字符串来创建DateTimeFormatter格式器 DateTimeFormatter.ofPattern("Gyyyy%%MMM%%dd HH:mm:ss")
};
// 依次使用不同的格式器对LocalDateTime进行格式化 System.out.println("开始使用DateTimeFormatter进行格式化");
for(int i = 0 ; i < formatters.length ; i++){
// 下面两行代码的作用相同
System.out.println(newTime.format(formatters[i]));
System.out.println(formatters[i].format(newTime));
}
控制台输出:
开始使用DateTimeFormatter进行格式化
2019-09-23
2019-09-23
15:42:47.06
15:42:47.06
2019-09-23T15:42:47.06
2019-09-23T15:42:47.06
2019年9月23日 星期一 15:42:47
2019年9月23日 星期一 15:42:47
下午03时42分47秒
下午03时42分47秒
公元2019%%九月%%23 15:42:47
公元2019%%九月%%23 15:42:47
OK,对于这几点的简单介绍到这里就差不多了,有兴趣的小伙伴可以自行深入研究~~
亲,博主的微信公众号
‘程序员小圈圈’开始持续更新了哟~~
识别二维码或者直接搜索名字 ‘程序员小圈圈’ 即可关注本公众号哟~~
不只是有技术哟~~
还有很多的学习娱乐资源免费下载哦~~
还可以学下教育知识以及消遣娱乐哟~~
求关注哟~~ ’