LocalDateTime用法(jdk1.8 )
前言
最近看别人项目源码,发现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);
运行结果:

根据指定日期/时间创建对象
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);
运行结果:

日期时间的加减
- 对于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"
);
//日期的减法用法一样,在此不再举例
运行结果:

将年、月、日等修改为指定的值,并返回新的日期(时间)对象
析: 其效果与时间日期相加减差不多,如今天是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"
);
运行结果:

获取日期的年月日周时分秒
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"
);
运行结果:

时间日期前后的比较与判断
//判断两个时间点的前后
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"
);
//注意,并没有获得秒差的,但既然可以获得毫秒,秒就可以自行获取了
运行结果:

当计算程序的运行时间时,应当使用时间戳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);
运行结果:

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

注:自定义转化的格式一定要与日期类型对应
- 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()));
运行结果:

将时间字符串形式转化为日期对象
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);
运行结果:

注:格式的写法必须与字符串的形式一样
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);
运行结果:

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);
运行结果:
LocalDateTime用法(jdk1.8 )的更多相关文章
- JDK8的LocalDateTime用法
参考资料:好好学Java https://mp.weixin.qq.com/s/Dd_7yUh3lq3TqE2cjsYXvw JDK8新特性里提供了3个时间类:LocalDate.LocalTime ...
- Java进阶篇之十五 ----- JDK1.8的Lambda、Stream和日期的使用详解(很详细)
前言 本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda.Stream和LocalDate日期的一些使用讲解. Lambda Lambda介绍 Lambda 表达式(lamb ...
- JDK8 的 Lambda、Stream、LocalDate
前言 本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda.Stream和LocalDate日期的一些使用讲解. 作者:虚无境 来源:cnblogs.com/xuwujing/ ...
- Java8新特性(三)——Optional类、接口方法与新时间日期API
一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...
- JDK1.8 LocalDateTime 时间类与字符互转
public static void main(String[] args) { DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPat ...
- @Override在JDK1.5和JDK1.6中用法区别
@Override 注解在jdk1.5环境下,只能用于对基类(父类)的方法的重写.而不能用于对实现的接口的方法的实现.而在jdk1.6环境下,两者都适用.
- JDK1.5新特性,基础类库篇,调用外部命令类(ProcessBuilder)用法
一. 背景 ProcessBuilder类是用来创建操作系统进程的.与Runtime.exec相比,它提供了更加方便的方法以创建子进程. 每个ProcessBuilder实例管理着一个进程属性的集合. ...
- jdk1.8新日期时间类(DateTime、LocalDateTime)demo代码
//获取当前时间 LocalDateTime d0 = LocalDateTime.now(); System.out.println(DataConvertUtil.localDateTimeToS ...
- LocalDateTime的一些用法
包括获取当前时间,指定特定时间.进行时间的加减等 LocalDateTime localDateTime3 = LocalDateTime.now(); LocalDate.now(); LocalT ...
随机推荐
- MySQL高可用架构之MySQL5.7.19 PXC
CentOS7.3下Percona-XtraDB-Cluster-5.7.19集群部署PXC三节点安装:node1:10.10.10.11 node2:10.10.10.12node3:10.10.1 ...
- windows10下安装docker报错:error during connect
详细报错信息如下: C:\Users\zig>docker info error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engin ...
- http://bbs.csdn.net/topics/340046630 dbgrid怎么获取当前记录值
这根grid无关,当你选中一条记录时,数据集就定位到这条数据上了,你只需要读取数据集中的数据就行了 对我有用[0] 丢个板砖[0] 引用 | 举报| 管理 hongss hongss 本版等级: ...
- JAVA在页面查看或下载服务器上的日志
1.配置 FileUtils类所需jar包的maven地址 <dependency> <groupId>commons-io</groupId> <artif ...
- Generative Model vs Discriminative Model
In this post, we are going to compare the two types of machine learning models-generative model and ...
- jmeter分布式压测 java.io.FileNotFoundException: rmi_keystore.jks (系统找不到指定的文件。)
解决办法:1.控制机和代理机:修改jmeter.properties中server.rmi.ssl.disable=true 不启动SSL2.控制机和代理机: Slave(从压力机)启动jmeter- ...
- nested exception is java.lang.NoClassDefFoundError: org/hibernate/validator/resourceloading/ResourceBundleLocator
原来的hibernate-validator-5.3.0.Final.jar里没有这个接口,换成 hibernate-validator-4.1.0.Final.jar 就好了
- Oracle数据库SQL语句的分类
1986年10月,美国国家标准协会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言,1987年在国际标准组织的支持下成为国际标准.不过各种通行的数据库系统其实在实践过程中都对SQL规范的作了 ...
- Oracle数据库的下载与安装
Oracle数据库下载: 推荐去Oracle官网下载 官方网址链接:https://www.oracle.com/database/technologies/oracle-database-softw ...
- TimeUnit类 java.util.concurrent.TimeUnit
TimeUnit是什么? TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段 主要作用 时间颗粒度转换 延时 常用的颗粒度 TimeUnit.DAYS ...