在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗?

通过阅读本篇文章你将了解到:

  • 为什么需要LocalDate、LocalTime、LocalDateTime【java8新提供的类】;

  • java8新的时间API的使用方式,包括创建、格式化、解析、计算、修改。

为什么需要LocalDate、LocalTime、LocalDateTime

1.Date如果不格式化,打印出的日期可读性差

Tue Sep 10 09:34:04 CST 2019

2.使用SimpleDateFormat对时间进行格式化,但SimpleDateFormat是线程不安全的SimpleDateFormat的format方法最终调用代码:

private StringBuffer format(Date date, StringBuffer toAppendTo,  FieldDelegate delegate) {  // Convert input date to time field list  calendar.setTime(date);  boolean useDateFormatSymbols = useDateFormatSymbols();  for (int i = 0; i < compiledPattern.length; ) {  int tag = compiledPattern[i] >>> 8;  int count = compiledPattern[i++] & 0xff;  if (count == 255) {  count = compiledPattern[i++] << 16;  count |= compiledPattern[i++];  }  switch (tag) {  case TAG_QUOTE_ASCII_CHAR:  toAppendTo.append((char)count);  break;  case TAG_QUOTE_CHARS:  toAppendTo.append(compiledPattern, i, count);  i += count;  break;  default:  subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);  break;  }  }  return toAppendTo;
}

calendar是共享变量,并且这个共享变量没有做线程安全控制。关注微信公众号:互联网架构师,在后台回复:2T,可以获取教程,都是干货。

当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值

另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。

在多并发情况下使用SimpleDateFormat需格外注意 SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。

parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了

a、重置日期对象cal的属性值b、使用calb中中属性设置calc、返回设置好的cal对象

但是这三步不是原子操作

多线程并发如何保证线程安全 - 避免线程之间共享一个SimpleDateFormat对象,每个线程使用时都创建一次SimpleDateFormat对象 => 创建和销毁对象的开销大 - 对使用format和parse方法的地方进行加锁 => 线程阻塞性能差 - 使用ThreadLocal保证每个线程最多只创建一次SimpleDateFormat对象 => 较好的方法

1.Date对时间处理比较麻烦,比如想获取某年、某月、某星期,以及n天以后的时间,如果用Date来处理的话真是太难了,你可能会说Date类不是有getYear、getMonth这些方法吗,获取年月日很Easy,但都被弃用了啊

Come On 一起使用java8全新的日期和时间API

LocalDate

只会获取年月日

创建LocalDate

//获取当前年月日
LocalDate localDate = LocalDate.now();
//构造指定的年月日
LocalDate localDate1 = LocalDate.of(2019, 9, 10);

获取年、月、日、星期几

int year = localDate.getYear();
int year1 = localDate.get(ChronoField.YEAR);
Month month = localDate.getMonth();
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.getDayOfMonth();
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);

LocalTime

只会获取几点几分几秒

创建LocalTime

LocalTime localTime = LocalTime.of(13, 51, 10);
LocalTime localTime1 = LocalTime.now();

获取时分秒

//获取小时
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
//获取分
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
//获取秒
int second = localTime.getSecond();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
LocalDateTime

获取年月日时分秒,等于LocalDate+LocalTime

创建LocalDateTime

LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
LocalDateTime localDateTime3 = localDate.atTime(localTime);
LocalDateTime localDateTime4 = localTime.atDate(localDate);

获取LocalDate

LocalDate localDate2 = localDateTime.toLocalDate();

获取LocalTime

LocalTime localTime2 = localDateTime.toLocalTime();
Instant

获取秒数

创建Instant对象

Instant instant = Instant.now();

获取秒数

long currentSecond = instant.getEpochSecond();

获取毫秒数

long currentMilli = instant.toEpochMilli();

个人觉得如果只是为了获取秒数或者毫秒数,使用System.currentTimeMillis()来得更为方便

修改LocalDate、LocalTime、LocalDateTime、Instant

LocalDate、LocalTime、LocalDateTime、Instant为不可变对象,修改这些对象对象会返回一个副本

增加、减少年数、月数、天数等 以LocalDateTime为例

LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
//增加一年
localDateTime = localDateTime.plusYears(1);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
//减少一个月
localDateTime = localDateTime.minusMonths(1);
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);

通过with修改某些值

//修改年为2019
localDateTime = localDateTime.withYear(2020);
//修改为2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);

还可以修改月、日

时间计算

比如有些时候想知道这个月的最后一天是几号、下个周末是几号,通过提供的时间和日期API可以很快得到答案

LocalDate localDate = LocalDate.now();
LocalDate localDate1 = localDate.with(firstDayOfYear());

比如通过firstDayOfYear()返回了当前日期的第一天日期,还有很多方法这里不在举例说明

格式化时间
LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);

DateTimeFormatter默认提供了多种格式化方式,如果默认提供的不能满足要求,

可以通过DateTimeFormatter的ofPattern方法创建自定义格式化方式

解析时间
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);

和SimpleDateFormat相比,DateTimeFormatter是线程安全的

小结

LocalDateTime:Date有的我都有,Date没有的我也有,日期选择请Pick Me

SpringBoot中应用LocalDateTime

将LocalDateTime字段以时间戳的方式返回给前端添加日期转化类

public class LocalDateTimeConverter extends JsonSerializer{  @Override  public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {  gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());  }
}

并在LocalDateTime字段上添加@JsonSerialize(using = LocalDateTimeConverter.class)注解,如下:

@JsonSerialize(using = LocalDateTimeConverter.class)
protected LocalDateTime gmtModified;

将LocalDateTime字段以指定格式化日期的方式返回给前端 在LocalDateTime字段上添加@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")注解即可,如下:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;

对前端传入的日期进行格式化 在LocalDateTime字段上添加@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解即可,如下:

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;

作者:何甜甜在吗
https://juejin.im/post/5d7787625188252388753eae

关注微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别

9、2T架构师学习资料干货分享

你还在用 Date?快使用 LocalDateTime 了!相关推荐

  1. 【Java】什么?你项目还在用Date表示时间?!日期类LocalDateTime的使用

    什么?你项目还在用Date表示时间?! 这都什么年代了,怎么还在用 Date来处理和表示时间! 别的先不说,我们先来看几个关于 Date用法的例子,这玩意真的好用吗? 一.我想新建一个表示" ...

  2. 什么?你项目还在用Date表示时间?!

     为啥会有这篇文章  最近接手了一个别人的老项目,拿到代码,导入IDEA的那一瞬间,我哭出了声 . . . 我瞥了一眼代码,就知道这次肯定遇到了屎山!因为我看到了这种代码: 我擦,这都什么年代了,怎么 ...

  3. 什么?你项目还在用Date表示时间?

     为啥会有这篇文章  最近接手了一个别人的老项目,拿到代码,导入IDEA的那一瞬间,我哭出了声 . . . 我瞥了一眼代码,就知道这次肯定遇到了屎山!因为我看到了这种代码: 我擦,这都什么年代了,怎么 ...

  4. 日期上午下午怎么用date存_Java12都要出来了,你还在使用Date操作日期吗?

    Java12都要出来了,你还在使用Date操作日期吗? 如果你想要用Date表示Java8的发布日期(2014年3月18日),需要创建这样的Date实例: Date date = new Date(1 ...

  5. java lang ill_请MATLAB高手帮忙我的MATLAB老出现以下东西,这些东东还刷的挺快,不按ESC都不停止.java.lang.Ill...

    请MATLAB高手帮忙我的MATLAB老出现以下东西,这些东东还刷的挺快,不按ESC都不停止.java.lang.Ill 请MATLAB高手帮忙 我的MATLAB老出现以下东西, 这些东东还刷的挺快, ...

  6. 你还在用 Date?建议使用 LocalDateTime 了!

    在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗? 通过阅读本篇文章你将了解到: 为什么需要LocalDate.Loc ...

  7. Java精粹--Date/Calendar/JodaTime/LocalDateTime解释

    点此查看全部文字教程.视频教程.源代码 本文目录 1. 不够好的开始 1.1 Date 日期时间类 1.2 Calendar 日历类 1.3 SimpleDateFormat 日期时间格式化 2. 足 ...

  8. 设计新奇的充电器,能搭积木还支持多口快充,IDMIX积木桌面充电器上手

    平时给手机.笔记本等设备充电的时候,大家一般会用原装的充电器,有时候同时充电的设备比较多,我们还需要加上一个插线板,然后配上三四个充电器,这样桌面上看起来未免有些凌乱,上周我发现了一款桌面充电器,支持 ...

  9. POSTGRESQL COPY 命令导入数据,你还另一个更快的方案!

    POSTGRESQL 数据库数据导入的核心一般都使用COPY 命令,熟悉POSTGRESQL 的同学应该对这个命令不陌生,相对于MYSQL 去一条条的执行insert命令来说,COPY 命令是POST ...

  10. 03Java常用API-19. Jdk8新增的日期Date API(LocalDateTime,LocalDate,LocalTime,Instant,Period,Duration)

    概述 LocalDateTime:包含了日期及时间. LocalDate:不包含具体时间的日期. LocalTime:不含日期的时间. Instant:代表的是时间戳. 获取日期时间的信息 Local ...

最新文章

  1. Visual SVN 非常好的转贴
  2. UGUI 自动布局的重叠BUG
  3. 【C++ Priemr | 15】虚函数常见问题
  4. ubuntu16.04升级 vim 8.0
  5. 开源组件XStream 修复11个漏洞并公开 PoC
  6. Total Defense Anti-Virus – 免费6个月
  7. jQuery UI dialog实现dialog弹框显示
  8. 支付宝当面付扫码支付支付后不回调_新开支付宝不满90天当面付收款第二天到账怎么办?如何实现秒到而不是冻结的来看看吧!...
  9. 【权限维持】window服务端常见后门技术
  10. JSP个人博客网站设计与实现
  11. 阜师院2016年c语言真题答案,C语言A卷答案.doc
  12. 通过Bellman算子理解动态规划
  13. config.py参数解释
  14. MATLAB注意事项
  15. Spring Boot 统一功能处理
  16. 股票中的KD指标金叉和死叉
  17. 阿里云ecs安全组管理(双可变宽带公网出口)
  18. 【akka】Akka源码分析-Event Bus
  19. C++ 获取jpg和png的图片宽和高,不使用第三方库
  20. fix协议的服务器,FIX 协议开发(3):QuickFIX/J 实战经验小结

热门文章

  1. 历时3个月终克2.1大礼包
  2. webpack vs gulp 一张图说明
  3. 智能城市即将爆发,WiFi行业再迎机遇
  4. 有关java中的集合List,set,Map 等
  5. Win9x 与 WinME 磁盘共享密码破解实战
  6. 看了这么多代码,谈一谈代码风格!
  7. 苹果mac视频和字幕下载软件:Downie
  8. indesign教程,如何改变内容的顺序?
  9. 如何在 Mac 上的 Pages 文稿中查找和替换文本?
  10. 如何将自定义消息添加到Mac锁屏