您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java各个时间类总结归纳,最全一篇

时间:2020-08-31 12:52:35  来源:  作者:

前言

本文主要针对DateCalendarInstantLocalDateLocalTimeLocalDateTime的使用做了介绍并进行了对比,同时对simpleDateFormatsimpleDateFormat进行了对比和介绍。篇幅较长可针对具体模块选择性阅读。

Date

对于Date类型最常用的操作想必就是new Date()了

 public static void main(String[] args) {
  System.out.println(new Date());
}

这时候我们会得到一个当前时间的一个Date类型的字段输出字样为Tue Jun 09 19:20:37 CST 2020 一个带有年月日时分秒的时间。

其中的CST可视为美国、澳大利亚、古巴或中国的标准时间,在这边就是中国的标准时间了。

当然我们对于这样格式的时间的做法是通过JAVA.text.SimpleDateFormat类来进行格式化之后返回页面展示

private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
  System.out.println(simpleDateFormat.format(new Date()));
}

输出为2020-06-09 19:43:21这个就是我们最为熟悉的一个时间字段格式化之后的结果了。

当然这里要友情提醒的是SimpleDateFormat这个类并不是线程安全的,在高并发场景下需要谨慎使用。Date类型自带有很多的函数具体如下:

Java各个时间类总结归纳,最全一篇

 


Java各个时间类总结归纳,最全一篇

 

可以发现很多都已经变成过时函数,虽然还可以使用但是并不保证在将来某个更新中被删除的可能性,我们也是不推荐使用这种过时的函数的。

这时候java.util.Calendar是一个不错的类可以帮我们解决很多问题。

相信一开始接触java的小伙伴一定被Calendar的强大征服过,但是用久了慢慢地我们会发现其实这个类并没有想象中那么强大,首先一个问题就是它并不支持时区,其次它也不是线程安全的。

所以考虑到它的种种缺陷,java8使用了新的时间和日期API LocalDateTime

Instant

Instant表示的是时间线上的一个点,也就是时刻,可以和Date做一个比较。

比较直接的一个不同就是Instant获取的是UTC的时间,而Date是根据当前服务器所处的环境的默认时区来获取的当前时间。

//Date案例
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
System.out.println("new Date() = "+date);
String s = simpleDateFormat.format(date);
System.out.println("SimpleDateFormat 格式化Date后 = "+s);
//Instant案例Instant instant = Instant.now();System.out.println("Instant = "+instant);
System.out.println("Instant +08:00 = "+instant.atOffset(ZoneOffset.ofHours(8)));

输出

new Date() = Wed Jun 10 15:27:48 CST 2020
SimpleDateFormat 格式化Date后 = 2020-06-10 15:27:48
Instant = 2020-06-10T07:27:48.198Z
Instant +08:00 = 2020-06-10T15:27:48.198+08:00

默认时区是UTC在使用Instant的时候是一个需要注意的点,也是容易忽略的一个点,这里划重点!相同的问题在LocalDate、LocalTime和LocalDateTime是不存在的。

但是Instant的官方描述来看,它是一个不可变的且线程安全的类

 * @implSpec
 * This class is immutable and thread-safe. * @since 1.8
 */public final class Instant implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable {}

有效时间范围是从-1000000000-01-01T00:00Z~-1000000000-01-01T00:00Z,可以满足大部分场景下的时刻现实问题。

同时在java8提供了toInsatant()和from()两个方法用于Date和Instant之间的来回转换

System.out.println("toInstant() = "+date.toInstant());
System.out.println("from() = "+Date.from(instant));

输出

toInstant() = 2020-06-10T07:45:42.440Z
from() = Wed Jun 10 15:45:42 CST 2020

可以看到相互转换过程中的时区问题不需要我们考虑,会自动+08:00或者-08:00。

比较头疼的一个事情就是java8没有针对Instant提供一个可供自定义的格式化类,所以这边我的解决方法是转换成LocalDateTime,再使用DateTimeFormatter来完成格式化。

System.out.println("Instant = " + LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

输出

Instant = 2020-06-10 16:02:26

这样就比较容易的解决了格式化的问题,当然你也可以自定义一个@config来完成对Instant的格式化,也不失为一种一劳永逸的方案。LocalDateTime和DateTimeFormatter在后面的内容中会做详细的介绍。

在讲解LocalDateTime之前我们先分别介绍一下LocalDate和LocalTime,以便于能更深入地理解LocalDateTime。

LocalDate和LocalTime

LocalDate

LocalDate首先是一个不可变类,默认格式为yyyy-MM-dd,其次它是一个只获取年月日的类,侧重点在日历而不是时间(这里我们需要把日历和时间这两个概念区分开)。

使用LocalDate.now()可以获取当前年月日,也可以使用LocalDate.of(year,month,dayOfMonth)来指定日期

public static void main(String[] args) {
  LocalDate today = LocalDate.now();  System.out.println("LocalDate.now() = "+today);
  today = LocalDate.of(2020,06,10);
  LocalDate laterDate = today.plusDays(30);
  System.out.println("LocalDate.of() = "+today.toString());
  System.out.println("plusDays = "+laterDate.toString());
  System.out.println("new Date() = "+ new Date());
}

输出

LocalDate.now() = 2020-06-09
LocalDate.of() = 2020-06-10
plusDays = 2020-07-10
new Date() = Tue Jun 09 20:31:22 CST 2020

从这个例子可以对比看出LocalDate和Date的不同。

同时作为一个访问器方法,LocalDate每次都是生成一个新的对象,而不是改变原有的对象的值。

可以从today.plusDays(30)中轻易地看到。与之类似的就是更改器方法,在java较早的版本中有一个类java.util.GregorianCalendar

public static void main(String[] args) {
  GregorianCalendar someDay = new GregorianCalendar(2020,06,9);
  System.out.println("before someDay = "+someDay.getTime());
  someDay.add(Calendar.DAY_OF_MONTH,30);
  System.out.println("after someDay = "+someDay.getTime());
}

输出

before someDay = Thu Jul 09 00:00:00 CST 2020
after someDay = Sat Aug 08 00:00:00 CST 2020

可以看到someDay的值随着函数add的调用一直在变化着,这与LocalDate大不一样,这是需要注意的一个点。

这边还需要注意一个点是localDate.getDayOfWeek().getValue(),LocalDate对于一周的枚举计数和Calendar有些不一样。

LocalDate一周是从周一开始计数对应的value值为1,周日结束对应的value值为7。

而Calendar一周是从周日开始计数对应的value值为1,周六结束对应的value为7,相比较下个人觉得LocalDate更加合理和好用一些。

LocalDate常用的方法如下:

图片来自java核心技术卷2

Java各个时间类总结归纳,最全一篇

 


Java各个时间类总结归纳,最全一篇

 

LocalTime

LocalTime与LocalDate类似同样是一个不可变类,默认格式是HH:mm:ss.zzz,可以看到它所关注的是当前的时刻。

public static void main(String[] args) {
  LocalTime localTime = LocalTime.now();  System.out.println("LocalTime.now() = "+localTime);
  localTime = LocalTime.of(8,8,8,888);
  System.out.println("LocalTime.of() = "+localTime);
  LocalTime laterTime = localTime.plusHours(2);
  System.out.println("localTime.plusHours() = "+laterTime);
  //根据时区获取当前时刻,同理适用与LocalDate
  LocalTime newlocalTime = LocalTime.now(ZoneId.of("America/New_York"));
  System.out.println("America/New_York Time = "+newlocalTime);
}

输出

LocalTime.now() = 20:58:54.941
LocalTime.of() = 08:08:08.000000888
localTime.plusHours() = 10:08:08.000000888
America/New_York Time = 08:58:54.944

这里我们会发现,尽管LocalTime默认的格式为HH:mm:ss.zzz,但是纳秒级别的精度它也是能支持的08:08:08.000000888。LocalTime常用的方法如下:

Java各个时间类总结归纳,最全一篇

 

java核心技术卷2

LocalDateTime

经过对LocalDate和LocalTime的介绍,LocalDateTime相信大家也已经知道如何使用了。

LocalDateTime也是一个不可变类且线程安全,它的默认格式为yyyy-MM-ddTHH:mm:ss.zzz,显然在日常的web开发过程中我们都会对这样的日期格式进行格式化,这就是我这边特别要提的一点了。

之前我们讲过java.text.SimpleDateFormat可以自定义格式化时间格式,但是他并不是线程安全的类,所以java8开始配合LocalDateTime提供了java.time.format.DateTimeFormatter来搞定这个问题。

 * @implSpec
 * This class is immutable and thread-safe. * * @since 1.8
 */public final class DateTimeFormatter

这是官方对他的介绍,这个类是不可变并且是线程安全的。所以我们可以放心地用了。

但是友情提醒下线程安全+线程安全不一定线程安全,不要误解了,这里就不展开讨论了。下面我们和SimpleDateFormat一起对比着来使用一下。

// LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now();String newLocalDateTime = localDateTime.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss"));
System.out.println("LocalDateTime =  "+localDateTime);
System.out.println("DateTimeFormatter 格式化后的时间 = "+newLocalDateTime);
//DateSimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
System.out.println("new Date() = "+date);
String s = simpleDateFormat.format(date);
System.out.println("SimpleDateFormat 格式化Date后 = "+s);

输出

LocalDateTime =  2020-06-10T14:41:02.546
DateTimeFormatter 格式化后的时间 = 2020-06-10 14:41:02
new Date() = Wed Jun 10 14:41:02 CST 2020
SimpleDateFormat 格式化Date后 = 2020-06-10 14:41:02

从代码量上就可以看到DateTimeFormatter的优势了,一行搞定。

相比一下SimpleDateFormat每次都要new一个对象,在极端情况下就会导致创建很多实例短时间无法回收而浪费很多内存空间,当然我们也可以通过使用静态变量通过添加synchronized来达到目的,但是同步块不可避免的问题就是阻塞。

当然你一定会说我可以使用ThreadLocal来创建副本来解决SimpleDateFormat的线程安全问题。这个是比较好的一个解决方案,如下:

private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
  @Override
  protected DateFormat initialValue() {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  }};
System.out.println("ThreadLocal = "+threadLocal.get().format(date));

输出

ThreadLocal = 2020-06-10 14:52:05

显然结果挺好的,但是使用LocalDateTime.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss"))一行就能解决了,相对而言是比较会更简洁和方便一些,所以推荐使用DateTimeFormatter。

作者|IT老哥|微信公众号



Tags:Java 时间类   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言本文主要针对Date、Calendar、Instant、LocalDate、LocalTime和LocalDateTime的使用做了介绍并进行了对比,同时对simpleDateFormat和simpleDateFormat进行了对比和介绍。...【详细内容】
2020-08-31  Tags: Java 时间类  点击:(47)  评论:(0)  加入收藏
Date类:1、Date类型转String类型(以时间格式1970-01-01 01:01:01为例)//yyyy-MM-dd HH:mm:ss表示24时间进制 SimpleDateFormat sDateFormat=new SimpleDateFormat("yyyy-MM-d...【详细内容】
2019-08-16  Tags: Java 时间类  点击:(332)  评论:(0)  加入收藏
▌简易百科推荐
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(11)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(12)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(10)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(10)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(14)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(17)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(21)  评论:(0)  加入收藏
一、概述观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者发现,这么想来目标发生情况到观察...【详细内容】
2021-12-13  唯一浩哥    Tags:Java   点击:(16)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条