往期热门文章:

1,《往期精选优秀博文都在这里了!》

2、呕心沥血总结的14张思维导图,教你构建 Python核心知识体系(附高清下载)

3、一份来自亚马逊技术专家的Google面试指南,GitHub收获9.8万星,已翻译成中文

4、支付宝系统架构(内部架构图)

5、牛逼!IDEA 2020 要本土化,真的是全中文了!中国开发者话语权越来越大了

来源 | 8rr.co/4KkS

在项目开发过程中经常遇到时间处理,但你真的用对了吗,理解阿里巴巴开发手册中禁用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 listcalendar.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是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。

在多并发情况下使用SimpleDateFormat需格外注意SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了:

  • 重置日期对象cal的属性值

  • 使用calb中中属性设置cal

  • 返回设置好的cal对象

但是这三步不是原子操作

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

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
```javaLocalDate 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

1.将LocalDateTime字段以时间戳的方式返回给前端

添加日期转化类

public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {@Overridepublic 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;

2.将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;

3.对前端传入的日期进行格式化

在LocalDateTime字段上添加@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解即可,如下:

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified
另:公众号后台回复【2T】有惊喜礼包!

推荐阅读 ↓↓↓

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

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

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

4.“37岁,985毕业,年薪50万,被裁掉只用了10分钟”

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

6.副业&接私活必备的 10 个开源项目!

7.你知道哪10大算法统治着全球吗?

8.15张图看懂瞎忙和高效的区别!

阿里规定代码中禁用这个,为何?相关推荐

  1. 阿里规定代码中禁用static修饰SimpleDateFormat,为何?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 来自:8rr.co/4KkS 在项目开发过程中经常遇到时间处理,但 ...

  2. simpledateformat 毫秒_阿里巴巴 | 为啥代码中禁用static修饰SimpleDateFormat?

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

  3. simpledateformat_为什么阿里巴巴规定代码中禁用 static 修饰 SimpleDateFormat?

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

  4. 接口中的成员只有静态常量和什么_为什么阿里工程师代码写的好?看看他的代码规范就知道了...

    摘要 本文主要讲解阿里JAVA开发手册中比较重要的设计规范,这些重要的设计规范有助于我们改进自己的代码,提升系统的系统的性能. 曾经与一位从阿里出来的Java工程师一起工作过一段时间,他的技术说不上非 ...

  5. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码...

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  6. MyEclipse中阿里JAVA代码规范插件(P3C)的安装及使用

    JAVA代码规范插件(P3C)是阿里巴巴2017年10月14日在杭州云栖大会上首发的,使之前的阿里巴巴JAVA开发手册正式以插件形式公开走向业界.插件的相关信息及安装包都可以在GitHub(https ...

  7. 老大,你为什么在代码中要求我们使用LocalDateTime而不是Date?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:何甜甜在吗    来源:http://1t.click/a7 ...

  8. 解读阿里官方代码规范

    2017年开春,阿里对外公布了「阿里巴巴Java开发手册」从头到尾浏览了一遍这份手册之后,感觉很棒.虽然其中的某些观点笔者不能苟同,但大部分的规范还是值得绝大多数程序员学习和遵守的. 笔者将对这份代码 ...

  9. 如何正确的使用Java8中的Optional类来消除代码中的null检查

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:一书生VOID lw900925.github.io/jav ...

  10. html禁止f12键代码,网站禁用f12 禁止调试代码方法

    正常情况下 自己的一些网站的一些代码不想被别人扒来扒去的,可以看看本方法. 可以设置复制提示,禁f12,禁止调试是很有必要的 当然这个防不了大佬,只能防防小学生 具体方法: 1.首先我们需要下载web ...

最新文章

  1. 保存Java程序状态及设置Properties文件
  2. OpenCv 金字塔之上采样与下采样
  3. Android getResources的作用和须要注意点
  4. DBMS_STATS.GATHER_TABLE_STATS详解
  5. Pwn环境配置(一)——安装虚拟机
  6. emacs 新手笔记(四) —— 使用 dired 完成一些简单的文件和目录操作
  7. hadoop Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out
  8. mongodb索引使用
  9. CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化
  10. [云原生专题-3]:云平台 - 云计算平台快速入门
  11. java开发mdm平台_Apple iOS MDM开发流程
  12. 高新兴中标4.61亿智慧城市PPP项目
  13. windows图片和传真查看器
  14. entity framework 新手入门篇(4)-entity framework扩展之 entityframework.extended
  15. win7 关闭计算机休眠,技术编辑教您win7下怎么关闭休眠
  16. 有什么好用的财务分析软件?
  17. AIS 2019(ACL IJCAI SIGIR)论文研讨会研究趋势汇总
  18. PC - 史上最简单的远程访问群晖 NAS 方法
  19. mysql创建外键时1025_navicat设置外键报错1025怎么办
  20. win7系统如何关闭安全模式,关闭安全模式的方法

热门文章

  1. 【学时总结】 ◆学时·IV◆ 数位DP
  2. 《BackTrack 5 Cookbook中文版——渗透测试实用技巧荟萃》—第3章3.4节识别在线设备...
  3. 智能家居实训系统的项目有感!
  4. 只身单车游山东(一)
  5. 如何在 iPhone、iPad 和 Mac 上通过 iMessage 共享照片和视频?
  6. PhotoMill X for Mac(图片批处理工具)
  7. 小白教程:如何在MAC菜单栏上显示日期和时间
  8. PostgreSQL Heap Only Tuple - HOT (降低UPDATE引入的索引写IO放大)
  9. WIDOWS 7全家桶(很详细)
  10. 安全SaaS调查品牌认知