JDK 1.8 完整日期时间Api (文末附示例)
一、背景
jdk 1.8
之前, Java
时间使用java.util.Date
和 java.util.Calendar
类。
Date today = new Date();
System.out.println(today);
// 转为字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String todayStr = sdf.format(today);
System.out.println(todayStr);
Date
的几个问题:
- 如果不格式化,
Date
打印出的日期可读性差; - 可以使用
SimpleDateFormat
对时间进行格式化,但SimpleDateFormat
是线程不安全的(阿里巴巴开发手册中禁用static
修饰SimpleDateFormat
); Date
对时间处理比较麻烦,比如想获取某年、某月、某星期,以及n
天以后的时间,如果用Date
来处理的话真是太难了,并且Date
类的getYear()
、getMonth()
这些方法都被弃用了;
二、JDK 1.8
新的日期时间类型
Java8
引入的新的一系列API
,对时间日期的处理提供了更好的支持,清楚的定义了时间日期的一些概念,比如说,瞬时时间(Instant
),持续时间(duration
),日期(date
),时间(time
),时区(time-zone
)以及时间段(Period
)。
LocalDate
:不包含时间的日期,比如2019-10-14
。可以用来存储生日,周年纪念日,入职日期等。LocalTime
:与LocalDate
想对照,它是不包含日期的时间。LocalDateTime
:包含了日期及时间,没有偏移信息(时区)。ZonedDateTime
:包含时区的完整的日期时间,偏移量是以UTC
/格林威治时间为基准的。Instant
:时间戳,与System.currentTimeMillis()
类似。Duration
:表示一个时间段。Period
:用来表示以年月日来衡量一个时间段。DateTimeFormatter
:新的日期解析格式化类。
2.1 LocalDate
LocalDate
类内只包含日期,不包含具体时间。只需要表示日期而不包含时间,就可以使用它。
public static void localDate() {
//获取当前年月日
LocalDate today = LocalDate.now();
System.out.println("当前年月日:" + today);
// 获取年的两种方式
int thisYear = today.getYear();
int thisYearAnother = today.get(ChronoField.YEAR);
System.out.println("今年是" + thisYear + "年");
System.out.println("今年是" + thisYearAnother + "年");
// 获取月
Month thisMonth = today.getMonth();
System.out.println(thisMonth.toString());
// 这是今年的第几个月(两种写法)
int monthOfYear = today.getMonthValue();
// int monthOfYear = today.get(ChronoField.MONTH_OF_YEAR);
System.out.println("这个月是今年的第" + monthOfYear + "个月");
// 月份的天数
int length = today.lengthOfMonth();
System.out.println("这个月有" + length + "天");
// 获取日的两种方式
int thisDay = today.getDayOfMonth();
int thisDayAnother = today.get(ChronoField.DAY_OF_MONTH);
System.out.println("今天是这个月的第" + thisDay + "天");
System.out.println("今天是这个月的第" + thisDayAnother + "天");
// 获取星期
DayOfWeek thisDayOfWeek = today.getDayOfWeek();
System.out.println(thisDayOfWeek.toString());
// 今天是这周的第几天
int dayOfWeek = today.get(ChronoField.DAY_OF_WEEK);
System.out.println("今天是这周的第" + dayOfWeek + "天");
// 是否为闰年
boolean leapYear = today.isLeapYear();
System.out.println("今年是闰年:" + leapYear);
//构造指定的年月日
LocalDate anotherDay = LocalDate.of(2008, 8, 8);
System.out.println("指定年月日:" + anotherDay);
}
2.2 LocalTime
LocalTime
只会获取时间,不获取日期。LocalTime
和LocalDate
类似,区别在于LocalDate不包含具体时间,而LocalTime
不包含具体日期。
public static void localTime() {
// 获取当前时间
LocalTime nowTime = LocalTime.now();
System.out.println("当前时间:" + nowTime);
//获取小时的两种方式
int hour = nowTime.getHour();
int thisHour = nowTime.get(ChronoField.HOUR_OF_DAY);
System.out.println("当前时:" + hour);
System.out.println("当前时:" + thisHour);
//获取分的两种方式
int minute = nowTime.getMinute();
int thisMinute = nowTime.get(ChronoField.MINUTE_OF_HOUR);
System.out.println("当前分:" + minute);
System.out.println("当前分:" + thisMinute);
//获取秒的两种方式
int second = nowTime.getSecond();
int thisSecond = nowTime.get(ChronoField.SECOND_OF_MINUTE);
System.out.println("当前秒:" + second);
System.out.println("当前秒:" + thisSecond);
// 构造指定时间(最多可到纳秒)
LocalTime anotherTime = LocalTime.of(20, 8, 8);
System.out.println("构造指定时间:" + anotherTime);
}
2.3 LocalDateTime
LocalDateTime
表示日期和时间组合。可以通过of()方法直接创建,也可以调用LocalDate
的atTime()
方法或LocalTime
的atDate()
方法将LocalDate
或LocalTime
合并成一个LocalDateTime
。
public static void localDateTime() {
// 当前日期和时间
LocalDateTime today = LocalDateTime.now();
System.out.println("现在是:" + today);
// 创建指定日期和时间
LocalDateTime anotherDay = LocalDateTime.of(2008, Month.AUGUST, 8, 8, 8, 8);
System.out.println("创建的指定时间是:" + anotherDay);
// 拼接日期和时间
// 使用当前日期,指定时间生成的 LocalDateTime
LocalDateTime thisTime = LocalTime.now().atDate(LocalDate.of(2008, 8, 8));
System.out.println("拼接的日期是:" + thisTime);
// 使用当前日期,指定时间生成的 LocalDateTime
LocalDateTime thisDay = LocalDate.now().atTime(LocalTime.of(12, 24, 12));
System.out.println("拼接的日期是:" + thisDay);
// 指定日期和时间生成 LocalDateTime
LocalDateTime thisDayAndTime = LocalDateTime.of(LocalDate.of(2008, 8, 8), LocalTime.of(12, 24, 12));
System.out.println("拼接的日期是:" + thisDayAndTime);
// 获取LocalDate
LocalDate todayDate = today.toLocalDate();
System.out.println("今天日期是:" + todayDate);
// 获取LocalTime
LocalTime todayTime = today.toLocalTime();
System.out.println("现在时间是:" + todayTime);
}
2.4 Instant
Instant
用于一个获取时间戳,与System.currentTimeMillis()
类似,但Instant
可以精确到纳秒。
public class InstantDemo {
public static void main(String[] args) {
// 创建Instant对象
Instant instant = Instant.now();
// 通过ofEpochSecond方法创建(第一个参数表示秒,第二个参数表示纳秒)
Instant another = Instant.ofEpochSecond(365 * 24 * 60, 100);
// 获取到秒数
long currentSecond = instant.getEpochSecond();
System.out.println("获取到秒数:" + currentSecond);
// 获取到毫秒数
long currentMilli = instant.toEpochMilli();
System.out.println("获取到毫秒数:" + currentMilli);
}
}
2.5 Duration
Duration
的内部实现与Instant
类似,但Duration
表示时间段,通过between
方法创建,还可以通过of()
方法创建。
public static void duration() {
LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
// 通过between()方法创建
Duration duration = Duration.between(from, to);
// 通过of()方法创建,该方法参数为时间段长度和时间单位。
// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);
}
2.5 Period
Period
与Duration
类似,获取一个时间段,只不过单位为年月日,也可以通过of
方法和between
方法创建,between
方法接收的参数为LocalDate
。
private static void period() {
// 通过of方法
Period period = Period.of(2012, 12, 24);
// 通过between方法
Period period1 = Period.between(LocalDate.now(), LocalDate.of(2020,12,31));
}
三、时间操作
3.1 时间比较
isBefore()
和isAfter()
判断给定的时间或日期是在另一个时间/日期之前还是之后。
以LocalDate
为例,LocalDateTime
/LocalTime
同理。
public static void compare() {
LocalDate thisDay = LocalDate.of(2008, 8, 8);
LocalDate otherDay = LocalDate.of(2018, 8, 8);
// 晚于
boolean isAfter = thisDay.isAfter(otherDay);
System.out.println(isAfter);
// 早于
boolean isBefore = thisDay.isBefore(otherDay);
System.out.println(isBefore);
}
3.2 增加/减少年数、月数、天数
以
LocalDateTime
为例,LocalDate
/LocalTime
同理。
public static void plusAndMinus() {
// 增加
LocalDateTime today = LocalDateTime.now();
LocalDateTime nextYearDay = today.plusYears(1);
System.out.println("下一年的今天是:" + nextYearDay);
LocalDateTime nextMonthDay = today.plus(1, ChronoUnit.MONTHS);
System.out.println("下一个月的今天是:" + nextMonthDay);
//减少
LocalDateTime lastMonthDay = today.minusMonths(1);
LocalDateTime lastYearDay = today.minus(1, ChronoUnit.YEARS);
System.out.println("一个月前是:" + lastMonthDay);
System.out.println("一年前是:" + lastYearDay);
}
3.3 时间修改
通过
with
修改时间
public static void edit() {
LocalDateTime today = LocalDateTime.now();
// 修改年为2012年
LocalDateTime thisYearDay = today.withYear(2012);
System.out.println("修改年后的时间为:" + thisYearDay);
// 修改为12月
LocalDateTime thisMonthDay = today.with(ChronoField.MONTH_OF_YEAR, 12);
System.out.println("修改月后的时间为:" + thisMonthDay);
}
3.4 时间计算
通过
TemporalAdjusters
的静态方法 和Duration
计算时间
public static void compute() {
// TemporalAdjusters 的静态方法
LocalDate today = LocalDate.now();
// 获取今年的第一天
LocalDate date = today.with(firstDayOfYear());
System.out.println("今年的第一天是:" + date);
// Duration 计算
LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusMonths(1);
Duration duration = Duration.between(from, to);
// 区间统计换算
// 总天数
long days = duration.toDays();
System.out.println("相隔" + days + "天");
// 小时数
long hours = duration.toHours();
System.out.println("相隔" + hours + "小时");
// 分钟数
long minutes = duration.toMinutes();
System.out.println("相隔" + minutes + "分钟");
}
TemporalAdjusters
的更多方法
方法名称 | 描述 |
---|---|
dayOfWeekInMonth() |
返回同一个月中每周的第几天 |
firstDayOfMonth() |
返回当月的第一天 |
firstDayOfNextMonth() |
返回下月的第一天 |
firstDayOfNextYear() |
返回下一年的第一天 |
firstDayOfYear() |
返回本年的第一天 |
firstInMonth() |
返回同一个月中第一个星期几 |
lastDayOfMonth() |
返回当月的最后一天 |
lastDayOfNextMonth() |
返回下月的最后一天 |
lastDayOfNextYear() |
返回下一年的最后一天 |
lastDayOfYear() |
返回本年的最后一天 |
lastInMonth() |
返回同一个月中最后一个星期几 |
next() / previous() |
返回后一个/前一个给定的星期几 |
nextOrSame() / previousOrSame() |
返回后一个/前一个给定的星期几,如果这个值满足条件,直接返回 |
四、时间日期格式化
4.1 格式化时间
DateTimeFormatter
默认提供了多种格式化方式,如果默认提供的不能满足要求,可以通过DateTimeFormatter
的ofPattern
方法创建自定义格式化方式。
public static void format() {
LocalDate today = LocalDate.now();
// 两种默认格式化时间方式
String todayStr1 = today.format(DateTimeFormatter.BASIC_ISO_DATE);
String todayStr2 = today.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println("格式化时间:" + todayStr1);
System.out.println("格式化时间:" + todayStr2);
//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String todayStr3 = today.format(dateTimeFormatter);
System.out.println("自定义格式化时间:" + todayStr3);
}
4.2 解析时间
4.1 中以何种方式格式化,这里需以同样方式解析。
public static void parse() {
LocalDate date1 = LocalDate.parse("20080808", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2008-08-08", DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(date1);
System.out.println(date2);
}
五、总结
相较于
Date
的优势
Instant
的精确度更高,可以精确到纳秒级;Duration
可以便捷得到时间段内的天数、小时数等;LocalDateTime
能够快速地获取年、月、日、下一月等;TemporalAdjusters
类中包含许多常用的静态方法,避免自己编写工具类;- 与
Date
的格式化方式SimpleDateFormat
相比,DateTimeFormatter
是线程安全的。
5.1 示例代码
5.2 技术交流
JDK 1.8 完整日期时间Api (文末附示例)的更多相关文章
- 一文告诉你Java日期时间API到底有多烂
前言 你好,我是A哥(YourBatman). 好看的代码,千篇一律!难看的代码,卧槽卧槽~其实没有什么代码是"史上最烂"的,要有也只有"史上更烂". 日期是商 ...
- 全面解析Java日期时间API
时区 GMT(Greenwich Mean Time):格林尼治时间,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间. UTC(Universal Time ...
- Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类
因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...
- Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析
目录 0.前言 1.TemporalAccessor源码 2.Temporal源码 3.TemporalAdjuster源码 4.ChronoLocalDate源码 5.LocalDate源码 6.总 ...
- 《Java 8实战》读书笔记系列——第三部分:高效Java 8编程(四):使用新的日期时间API
https://www.lilu.org.cn/https://www.lilu.org.cn/ 第十二章:新的日期时间API 在Java 8之前,我们常用的日期时间API是java.util.Dat ...
- java 数据结构(三):java常用类 三 日期时间API
JDK 8之前日期时间API 1.获取系统当前时间:System类中的currentTimeMillis()long time = System.currentTimeMillis();//返回当前时 ...
- Java 8 日期时间 API
转自:https://www.runoob.com/java/java8-datetime-api.html Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与 ...
- JDK8 新增的日期时间API
背景 JDK8中增加了一套全新的日期时间API,这里进行总结下,方便查询使用. 新的时间及日期API位于 java.time 包中,下面是一些关键类. Instant:代表的是时间戳. LocalDa ...
- Java 8 新特性-菜鸟教程 (8) -Java 8 日期时间 API
Java 8 日期时间 API Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理. 在旧版的 Java 中,日期时间 API 存在诸多问题,其中有: ...
随机推荐
- 工厂设计模式灵魂拷问-Java实现
show me the code and take to me,做的出来更要说的明白 GitHub项目JavaHouse同步收录 喜欢就点个赞呗! 你的支持是我分享的动力! 引入 我们经常听到工厂模式 ...
- iOS-NSNotificationCenter通知原理解析
一.基本概念 NSNotification和NSNotificationCenter是使用观察者模式来实现的用于跨层传递消息. NSNotificationCenter采用单例模式. 二.基本实现 通 ...
- 机器学习算法概述第五章——CART算法
特点: 是一个二叉树,元素可以重复利用,可以做回归也可以做分类,分类用最小二乘法,即误差平方和最小 切割方法: 对于可量化的x来说: 切割点通常为两个x的平均值 左右两部分分别取均值,再评判以哪个分割 ...
- 深入Synchronized的实现原理与源码分析
前言 一.synchronized的特性 1.1 原子性 1.2 可见性 1.3 有序性 1.4 可重入性 二.synchronized的用法 三.synchronized锁的实现 3.1 同步方法 ...
- Python综合应用:教你用字符打印一张怀旧风格的照片
1. 前言第一次在学校机房里见到计算机,还是上古时期.计算机型号大概是LASER-310吧,有点记不清了.那会儿,显示器还是单色的,只能显示文本,每行最多显示80个字符.想看图片,印象中只能用针式打印 ...
- 「Luogu P2201」数列编辑器 解题报告
数列编辑器,在线IDE 本期的主题是洛谷的在线IDE 小学生?!小学生虐我
- .net core 3.0 搭建 IdentityServer4 验证服务器
叙述 最近在搞 IdentityServer4 API接口认证部分,由于之前没有接触过 IdentityServer4 于是在网上一顿搜搜搜,由于自己技术水平也有限,看了好几篇文章才搞懂,想通过博客 ...
- 2019HDU多校第四场题解
1001.AND Minimum Spanning Tree 传送门:HDU6614 题意:给你一个又n个点的完全图,点编号从1~n,每条边的权值为被连接的两点编号按位与后的值.现在要你找到最小生成树 ...
- static和final关键字
static关键字 静态变量 静态变量:又称做类变量,也就是这个变量属于整个类,而不属于单个实例.类所有的实例共享静态变量,可以直接通过类名来访问它.静态变量在内存中只存在一份,当系统第一次加载类时, ...
- TensorFlow——LinearRegression简单模型代码
代码函数详解 tf.random.truncated_normal()函数 tf.truncated_normal函数随机生成正态分布的数据,生成的数据是截断的正态分布,截断的标准是2倍的stddev ...