LocalDateTime用法(jdk1.8 )

Stella981
• 阅读 523

前言

最近看别人项目源码,发现Java8新的日期时间API很方便强大,所以转载该入门介绍博客,记录一下。

使用新时间日期API的必要性

在java8以前,或许:

  • 当你在做有关时间日期的操作时,你会想到用Date;
  • 当你在做日期、月份、天数相加减时,你会想到用Calendar;
  • 当你需要对时间日期进行格式化时,你会想到使用SimpleDateFormat或DateFormat下的其他子类;
    ……

但是,你必须知道,以上有关的时间日期操作对象,都是可变的、线程不安全的,同时,如果作为一个经常写过类似代码的人来说,尽管有相关对象提供某些操作,但并不能很快、很简单的就能得到最终想要的结果,如:要计算两个时间点之间相差的年、月、日、周、时、分、秒等,这些计算尽管原有API也能够实现,但原有API除了线程不安全之外,另外一个不足之处就是代码繁琐,性能低!

为何我们总提多线程下,线程不安全?对于初学者来说,可能觉得能够简单实现出功能就已经足够,但是真正的开发项目是不可能仅仅考虑功能的实现的,还要考虑项目的安全性、稳定性、高性能、高可用性等等!因此,作为java开发者,多线程的知识是必不可少的。而也正因为多线程,才会出现一大堆问题(简称线程安全性问题),作为开发者,就应该写出不仅能实现功能的代码,还要是线程安全的代码。那么,学习并熟悉掌握新的线程安全的API就显得非常重要了!

没错,java8出的新的时间日期API都是线程安全的,并且性能更好,代码更简洁!

新时间日期API常用、重要对象介绍

  • ZoneId: 时区ID,用来确定Instant和LocalDateTime互相转换的规则
  • Instant: 用来表示时间线上的一个点(瞬时)
  • LocalDate: 表示没有时区的日期, LocalDate是不可变并且线程安全的
  • LocalTime: 表示没有时区的时间, LocalTime是不可变并且线程安全的
  • LocalDateTime: 表示没有时区的日期时间, LocalDateTime是不可变并且线程安全的
  • Clock: 用于访问当前时刻、日期、时间,用到时区
  • Duration: 用秒和纳秒表示时间的数量(长短),用于计算两个日期的“时间”间隔
  • Period: 用于计算两个“日期”间隔

其中,LocalDate、LocalTime、LocalDateTime是新API里的基础对象,绝大多数操作都是围绕这几个对象来进行的,有必要搞清楚:

LocalDate : 只含年月日的日期对象
LocalTime :只含时分秒的时间对象
LocalDateTime : 同时含有年月日时分秒的日期对象

本文将以实例讲解日常开发中常用到的时间日期操作,如:

获取当前日期、时间
指定时间日期创建对应的对象
计算两个时间点的间隔
判断两个时间的前后
时间日期的格式化
获取时间戳
时间、日期相加减
获取给定时间点的年份、月份、周、星期等
……

新时间日期API详解与示例

获取当前时间
LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDate); System.out.println(localTime); System.out.println(localDateTime); 

运行结果:

image.png

根据指定日期/时间创建对象
LocalDate localDate = LocalDate.of(2018, 1, 13); LocalTime localTime = LocalTime.of(9, 43, 20); LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 13, 9, 43, 20); System.out.println(localDate); System.out.println(localTime); System.out.println(localDateTime); 

运行结果:

image.png

日期时间的加减
  • 对于LocalDate,只有精度大于或等于日的加减,如年、月、日;

  • 对于LocalTime,只有精度小于或等于时的加减,如时、分、秒、纳秒;

  • 对于LocalDateTime,则可以进行任意精度的时间相加减;

    LocalDateTime localDateTime = LocalDateTime.now(); //以下方法的参数都是long型,返回值都是LocalDateTime LocalDateTime plusYearsResult = localDateTime.plusYears(2L); LocalDateTime plusMonthsResult = localDateTime.plusMonths(3L); LocalDateTime plusDaysResult = localDateTime.plusDays(7L); LocalDateTime plusHoursResult = localDateTime.plusHours(2L); LocalDateTime plusMinutesResult = localDateTime.plusMinutes(10L); LocalDateTime plusSecondsResult = localDateTime.plusSeconds(10L); System.out.println("当前时间是 : " + localDateTime + "\n" + "当前时间加2年后为 : " + plusYearsResult + "\n" + "当前时间加3个月后为 : " + plusMonthsResult + "\n" + "当前时间加7日后为 : " + plusDaysResult + "\n" + "当前时间加2小时后为 : " + plusHoursResult + "\n" + "当前时间加10分钟后为 : " + plusMinutesResult + "\n" + "当前时间加10秒后为 : " + plusSecondsResult + "\n" ); //也可以以另一种方式来相加减日期,即plus(long amountToAdd, TemporalUnit unit) // 参数1 : 相加的数量, 参数2 : 相加的单位 LocalDateTime nextMonth = localDateTime.plus(1, ChronoUnit.MONTHS); LocalDateTime nextYear = localDateTime.plus(1, ChronoUnit.YEARS); LocalDateTime nextWeek = localDateTime.plus(1, ChronoUnit.WEEKS); System.out.println("now : " + localDateTime + "\n" + "nextYear : " + nextYear + "\n" + "nextMonth : " + nextMonth + "\n" + "nextWeek :" + nextWeek + "\n" ); //日期的减法用法一样,在此不再举例

运行结果:

image.png

将年、月、日等修改为指定的值,并返回新的日期(时间)对象

析: 其效果与时间日期相加减差不多,如今天是2018-01-13,要想变为2018-01-20有两种方式
a. localDate.plusDays(20L) -> 相加指定的天数
b. localDate.withDayOfYear(20) -> 直接指定到哪一天

LocalDate localDate = LocalDate.now(); //当前时间基础上,指定本年当中的第几天,取值范围为1-365,366 LocalDate withDayOfYearResult = localDate.withDayOfYear(200); //当前时间基础上,指定本月当中的第几天,取值范围为1-29,30,31 LocalDate withDayOfMonthResult = localDate.withDayOfMonth(5); //当前时间基础上,直接指定年份 LocalDate withYearResult = localDate.withYear(2017); //当前时间基础上,直接指定月份 LocalDate withMonthResult = localDate.withMonth(5); System.out.println("当前时间是 : " + localDate + "\n" + "指定本年当中的第200天 : " + withDayOfYearResult + "\n" + "指定本月当中的第5天 : " + withDayOfMonthResult + "\n" + "直接指定年份为2017 : " + withYearResult + "\n" + "直接指定月份为5月 : " + withMonthResult + "\n" ); 

运行结果:

image.png

获取日期的年月日周时分秒
LocalDateTime localDateTime = LocalDateTime.now(); int dayOfYear = localDateTime.getDayOfYear(); int dayOfMonth = localDateTime.getDayOfMonth(); DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); System.out.println("今天是" + localDateTime + "\n" + "本年当中第" + dayOfYear + "天" + "\n" + "本月当中第" + dayOfMonth + "天" + "\n" + "本周中星期" + dayOfWeek.getValue() + "-即" + dayOfWeek + "\n"); //获取当天时间的年月日时分秒 int year = localDateTime.getYear(); Month month = localDateTime.getMonth(); int day = localDateTime.getDayOfMonth(); int hour = localDateTime.getHour(); int minute = localDateTime.getMinute(); int second = localDateTime.getSecond(); System.out.println("今天是" + localDateTime + "\n" + "年 : " + year + "\n" + "月 : " + month.getValue() + "-即 "+ month + "\n" + "日 : " + day + "\n" + "时 : " + hour + "\n" + "分 : " + minute + "\n" + "秒 : " + second + "\n" ); 

运行结果:

image.png

时间日期前后的比较与判断
//判断两个时间点的前后
LocalDate localDate1 = LocalDate.of(2017, 8, 8); LocalDate localDate2 = LocalDate.of(2018, 8, 8); boolean date1IsBeforeDate2 = localDate1.isBefore(localDate2); System.out.println("date1IsBeforeDate2 : " + date1IsBeforeDate2); // date1IsBeforeDate2 == true 
判断是否为闰年
LocalDate now = LocalDate.now(); System.out.println("now : " + now + ", is leap year ? " + ); 
java8时钟 : clock()
//返回当前时间,根据系统时间和UTC
Clock clock = Clock.systemUTC(); // 运行结果: SystemClock[Z] System.out.println(clock); 
时间戳

事实上Instant就是java8以前的Date,
可以使用以下两个类中的方法在这两个类型之间进行转换,
比如Date.from(Instant)就是用来把Instant转换成java.util.date的,
而new Date().toInstant()就是将Date转换成Instant的

Instant instant = Instant.now(); //2019-06-08T16:50:19.174Z System.out.println(instant); Date date = Date.from(instant); Instant instant2 = date.toInstant(); //Sun Jun 09 00:50:19 CST 2019 System.out.println(date); //2019-06-08T16:50:19.174Z System.out.println(instant2); 
计算时间、日期间隔

Duration:用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔

//计算两个日期的日期间隔-年月日
LocalDate date1 = LocalDate.of(2018, 2, 13); LocalDate date2 = LocalDate.of(2017, 3, 12); //内部是用date2-date1,所以得到的结果是负数 Period period = Period.between(date1, date2); System.out.println("相差年数 : " + period.getYears()); System.out.println("相差月数 : " + period.getMonths()); System.out.println("相差日数 : " + period.getDays()); //还可以这样获取相差的年月日 System.out.println("-------------------------------"); long years = period.get(ChronoUnit.YEARS); long months = period.get(ChronoUnit.MONTHS); long days = period.get(ChronoUnit.DAYS); System.out.println("相差的年月日分别为 : " + years + "," + months + "," + days); //注意,当获取两个日期的间隔时,并不是单纯的年月日对应的数字相加减,而是会先算出具体差多少天,在折算成相差几年几月几日的 //计算两个时间的间隔 System.out.println("-------------------------------"); LocalDateTime date3 = LocalDateTime.now(); LocalDateTime date4 = LocalDateTime.of(2018, 1, 13, 22, 30, 10); Duration duration = Duration.between(date3, date4); System.out.println(date3 + " 与 " + date4 + " 间隔 " + "\n" + " 天 :" + duration.toDays() + "\n" + " 时 :" + duration.toHours() + "\n" + " 分 :" + duration.toMinutes() + "\n" + " 毫秒 :" + duration.toMillis() + "\n" + " 纳秒 :" + duration.toNanos() + "\n" ); //注意,并没有获得秒差的,但既然可以获得毫秒,秒就可以自行获取了 

运行结果:

image.png

当计算程序的运行时间时,应当使用时间戳Instant

Instant ins1 = Instant.now(); for (int i = 0; i < 10000000; i++) { //循环一百万次 } Instant ins2 = Instant.now(); Duration duration = Duration.between(ins1, ins2); System.out.println("程序运行耗时为 : " + duration.toMillis() + "毫秒"); 
时间日期的格式化(格式化后返回的类型是String)
1. 使用jdk自身配置好的日期格式
//使用jdk自身配置好的日期格式
DateTimeFormatter formatter1 = DateTimeFormatter.ISO_DATE_TIME; LocalDateTime date1 = LocalDateTime.now(); //反过来调用也可以 : date1.format(formatter1); String date1Str = formatter1.format(date1); System.out.println(date1Str); 

运行结果:

image.png

2. 使用自定义格式
LocalDateTime date1 = LocalDateTime.now(); DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); String date2Str = formatter2.format(date1); System.out.println(date2Str); 

运行结果:

image.png

注:自定义转化的格式一定要与日期类型对应

  • LocalDate只能设置仅含年月日的格式
  • LocalTime只能设置仅含时分秒的格式
  • LocalDateTime可以设置含年月日时分秒的格式

代码如下:

DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); System.out.println(formatter3.format(LocalDate.now())); System.out.println("-------------------------------"); DateTimeFormatter formatter4 = DateTimeFormatter.ofPattern("HH:mm:ss"); System.out.println(formatter4.format(LocalTime.now())); 

运行结果:

image.png

将时间字符串形式转化为日期对象
String datetime =  "2018-01-13 21:27:30";  
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime ldt = LocalDateTime.parse(datetime, dtf); System.out.println(ldt); 

运行结果:

image.png

注:格式的写法必须与字符串的形式一样
2018-01-13 21:27:30 对应 yyyy-MM-dd HH:mm:ss
20180113213328 对应 yyyyMMddHHmmss
否则会报运行时异常!

但要记住:得到的最终结果都是类似2018-01-13T21:27:30的格式

因为在输出LocalDateTime对象时,会调用其重写的toString方法。

@Override
    public String toString() { return date.toString() + 'T' + time.toString(); } 
将时间日期对象转为格式化后的时间日期对象
//新的格式化API中,格式化后的结果都默认是String,有时我们也需要返回经过格式化的同类型对象
LocalDateTime ldt1 = LocalDateTime.now(); DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String temp = dtf1.format(ldt1); LocalDateTime formatedDateTime = LocalDateTime.parse(temp, dtf1); System.out.println(formatedDateTime); 

运行结果:

image.png

long毫秒值转换为日期
System.out.println("---------long毫秒值转换为日期---------"); DateTimeFormatter df= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String longToDateTime = df.format(LocalDateTime.ofInstant( Instant.ofEpochMilli(System.currentTimeMillis()),ZoneId.of("Asia/Shanghai"))); System.out.println(longToDateTime); 

运行结果:

地址: https://www.jianshu.com/p/ceb1df475021

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Wesley13 Wesley13
2年前
java8时间工具类Localdate、LocaldateTime
优点:1.方便。Date只能是日期加时间的格式,而LocalDate、LocalTime、LocalDateTime 分别代表日期,时间,日期时间,非常灵活。再就是后者在日期计算及格式化方面非常简单易用,而Date要繁琐很多。2.线程安全。传统时间类不支持多线程安全。缺点<目前发现的坑:1.在比较日期相隔
皕杰报表(关于日期时间时分秒显示不出来)
在使用皕杰报表设计器时,数据据里面是日期型,但当你web预览时候,发现有日期时间类型的数据时分秒显示不出来,只有年月日能显示出来,时分秒显示为0:00:00。1.可以使用tochar解决,数据集用selecttochar(flowdate,"yyyyMMddHH:mm:ss")fromtablename2.也可以把数据库日期类型date改成timestamp
Karen110 Karen110
2年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
2年前
Python time模块 返回格式化时间
常用命令  strftimetime.strftime("%Y%m%d%H:%M:%S",formattime)第二个参数为可选参数,不填第二个参数则返回格式化后的当前时间日期201812112:00:00time.strftime('%H:%M:%S')返回当前时间的时分秒time.strftim
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这