文章目录
Java 8 日期和时间
为什么Java8提供了新的日期与时间的API?
官方是这么解释的:
Why do we need a new date and time library?
A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.
For example, the existing classes (such as
java.util.Date
andSimpleDateFormatter
) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.Some of the date and time classes also exhibit quite poor API design. For example, years in
java.util.Date
start at 1900, months start at 1, and days start at 0—not very intuitive.These issues, and several others, have led to the popularity of third-party date and time libraries, such as Joda-Time.
In order to address these problems and provide better support in the JDK core, a new date and time API, which is free of these problems, has been designed for Java SE 8.
The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package
java.time
.
参考链接:官方文档
总的来说就是以前写的Date API不好用,而且存在一些线程安全问题,给开发人员造成很多的烦恼,以至于开发人员需要使用其他优秀第三方的日期API,比如Joda-Time。Oracle可能实在忍不了,所以根据Joda-Time API中的一些优秀设计,设计了Java8的Date和Time,放在了新的包下java.time
。
简单概述
-
在
java.time
包中,Instant
类表示时间线上的一个点,通常用于对时间进行操作。LocalDate
类为没有时间和时区部分的日期,例如:2021-02-24
。
如果你需要日期和时间,就选择LocalDateTime
,例如:2021-02-24T13:49:10.758276300
。
如果你需要一段时间但不关心日期,那么可以使用LocalTime
,例如:13:50:26.058539700
。
如果时区很重要,日期和时间API提供ZonedDateTime
类。 顾名思义,这个类表示带有时区日期时间。 -
然后有两个类来测量时间总计,即
Duration
类和Period
类。 这两个类是相似的,除了Duration
是基于时间,但而Period
是基于日期的。Duration
提供了纳秒精度的时间量。 例如,可以模拟飞行时间,因为它通常以小时数和分钟数表示。 另一方面,如果只关心天数,月数或年数,例如计算一个人的年龄,则Period
更为适用。 -
java.time
包也带有两个枚举DayOfWeek
和Month
。DayOfWeek
表示从一周的一天,从周一开始到周日。Month
枚举代表这一年的十二个月,从1月到12月。 -
处理日期和时间通常涉及解析和格式。 日期和时间API通过在所有主要类中提供
parse
和format
方法来解决这两个问题。 另外,java.time.format
包含一个用于格式化日期和时间的DateTimeFormatter
类。
Instant类
Instant 没有时区信息(也可以认为是0时区,即GMT时区),Instant实例表示时间线上的一个点。 参考点是标准的Java纪元(epoch),即1970-01-01T00:00:00Z
(1970年1月1日00:00 GMT
)。
Instant
的静态now
方法返回一个表示当前时间的Instant
对象。
getEpochSecond
方法返回自纪元以来经过的秒数。 getNano
方法返回自上一秒开始以来的纳秒数。
Instant
类的一个常用用途是用来操作时间。
@Test
void testTime1() throws InterruptedException {
Instant start = Instant.now();
// do something here
TimeUnit.MILLISECONDS.sleep(100);
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
如上面代码所示,Duration
类用于返回两个Instant
之间时间数量的差异。
Instant与Date的转换
Instant
相当于Date
@Test
void testTime2() {
//instant 相当于 date
Instant instant = Instant.now();
System.out.println(instant); //2021-02-24T06:53:58.933542200Z
Date date = new Date();
System.out.println(date); //Wed Feb 24 14:53:58 CST 2021
//instant转date 类方法(java.util.date)
Date from = Date.from(instant);
System.out.println(from); // Wed Feb 24 14:53:58 CST 2021
//date 转instant 对象方法(java.util.date)
Instant instant1 = date.toInstant();
System.out.println(instant1); //2021-02-24T06:53:58.944Z
//instant 根据毫秒值或者date转换为instant 类方法 (java.time)
Instant instant2 = Instant.ofEpochMilli(date.getTime());
System.out.println(instant2); //2021-02-24T06:53:58.944Z
}
将字符串类型的Instant转换为Instantd对象
注意:必须传入的是符合 UTC格式的字符串
@Test
void testTime3() {
Instant parse = Instant.parse("2021-02-24T08:59:10.142029600Z");
System.out.println(parse);//2021-02-24T08:59:10.142029600Z
}
Instant的加減操作
@Test
void testTime4() {
//instant 在现有的instant的时间上追加些时间,下面例子追加了5小时10分钟,这里plus会产生新的instant对象
Instant instant = Instant.now();
Instant plus = instant.plus(Duration.ofHours(5).plusMinutes(10));
System.out.println("instant:" + instant + ", plus:" + plus);//instant:2021-02-26T05:30:55.385967500Z, plus:2021-02-26T10:40:55.385967500Z
System.out.println(instant == plus);//plus会产生新的instant对象 所以结果位false
//instant 获取其5天前的instant(此刻)
Instant minus = instant.minus(5, ChronoUnit.HOURS);
System.out.println("instant:" + instant + ", minus:" + minus);//instant:2021-02-26T05:30:55.385967500Z, minus:2021-02-26T00:30:55.385967500Z
//也可以直接调用相关减法方法,效果跟上面的方法一样
Instant minus1 = instant.minusSeconds(60 * 60 * 5);
System.out.println("instant:" + instant + ", minus1:" + minus1);//instant:2021-02-26T05:30:55.385967500Z, minus1:2021-02-26T00:30:55.385967500Z
//减法方法,效果跟上面的方法一样
Instant minus2 = instant.minus(Duration.ofHours(5));
System.out.println("instant:" + instant + ", minus2:" + minus2);//instant:2021-02-26T05:30:55.385967500Z, minus2:2021-02-26T00:30:55.385967500Z
}
Instant时间差计算
@Test
void testTime5() throws InterruptedException {
//计算两个Instant之间的秒数, ChronoUnit用的什么,得到的结果就是什么单位
Instant instant = Instant.now();
TimeUnit.SECONDS.sleep(2);
Instant instant2 = Instant.now();
long between = ChronoUnit.SECONDS.between(instant, instant2);
long between2 = Duration.between(instant, instant2).toSeconds();
System.out.println(between);//2
System.out.println(between2);//2
}
Instant时间大小比较
@Test
void testTime6() throws InterruptedException {
Instant instant = Instant.now();
TimeUnit.SECONDS.sleep(2);
Instant instant2 = Instant.now();
//比较两个instant 相等 0, 前者时间纳秒值大于后者 1,小于后者 -1或小于0
int i = instant.compareTo(instant2);
System.out.println(i);//-1
//判断instant时间前后,前者在后者之后返回true,反之false
boolean after = instant.isAfter(instant2);
System.out.println(after);//false
//判断instant时间前后,前者在后者之前返回true,反之false,正好与上面相反
boolean before = instant.isBefore(instant2);
System.out.println(before);//true
}
Instant详解
通过Instant.now()
获得的时间戳与北京时间相差八个小时,这是因为Instant.now()
使用的是UTC时间,如果要转化为北京时间需要加上八个小时
/**
* Obtains the current instant from the system clock.
* <p>
* This will query the {@link Clock#systemUTC() system UTC clock} to
* obtain the current instant.
* <p>
* Using this method will prevent the ability to use an alternate time-source for
* testing because the clock is effectively hard-coded.
*
* @return the current instant using the system clock, not null
*/
public static Instant now() {
return Clock.systemUTC().instant();
}
而。LocalDate
、LocalDateTime
的now()
方法使用的是系统默认时区 不存在Instant.now()
的时间问题。
Instant.now()转化为北京时间
@Test
void testTime7() {
Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
System.out.println("now:"+now);//now:2021-02-26T13:51:40.324904700Z
}
LocalDate类
方法 | 描述 |
---|---|
now | 静态方法,返回今天的日期 |
of | 从指定年份,月份和日期创建LocalDate的静态方法 |
getDayOfMonth, getMonthValue, getYear | 以int形式返回此LocalDate的日,月或年 |
getMonth | 以Month枚举常量返回此LocalDate的月份 |
plusDays, minusDays | 给LocalDate添加或减去指定的天数 |
plusWeeks, minusWeeks | 给LocalDate添加或减去指定的星期数 |
plusMonths, minusMonths | 给LocalDate添加或减去指定的月份数 |
plusYears, minusYears | 给LocalDate添加或减去指定的年数 |
isLeapYear | 检查LocalDate指定的年份是否为闰年 |
isAfter, isBefore | 检查此LocalDate是在给定日期之后还是之前 |
lengthOfMonth | 返回此LocalDate中月份的天数 |
withDayOfMonth | 返回此LocalDate的拷贝,将月份中的某天设置为给定值 |
withMonth | 返回此LocalDate的拷贝,其月份设置为给定值 |
withYear | 返回此LocalDate的拷贝,并将年份设置为给定值 |
创建LocalDate的方式
LocalDate
提供了许多创建日期的方法。
@Test
void testLocalDate1() {
LocalDate localDate = LocalDate.now();
System.out.println(localDate);//2021-02-26
LocalDate date = LocalDate.of(2018, 3, 7);
System.out.println(date);//2018-03-07
LocalDate date2 = LocalDate.of(2018, Month.MARCH, 7);
System.out.println(date2);//2018-03-07
}
LocalDate获取日,月,年
@Test
void testLocalDate2() {
//LocalDate的日,月或年的方法,例如getDayOfMonth,getMonth,getMonthValue和getYear。他们都没有任何参数,并返回一个int或Month的枚举常量。
LocalDate localDate = LocalDate.now();
System.out.println(localDate.getDayOfYear());//61
System.out.println(localDate.getDayOfMonth());//2
Month month = localDate.getMonth(); //Month的枚举常量。
System.out.println(month);//MARCH
System.out.println(localDate.getYear());//2021
System.out.println(localDate.getMonthValue());//2
//get方法,接受一个TemporalField并返回这个LocalDate的一部分。 例如,传递ChronoField.YEAR以获取LocalDate的年份部分。
//ChronoField是一个实现TemporalField接口的枚举
int year = localDate.get(ChronoField.YEAR);
System.out.println(year);//2021
}
LocalDate的加减操作
@Test
void testLocalDate3() {
LocalDate now = LocalDate.now();
System.out.println(now);//2021-03-02
LocalDate plusDays = now.plusDays(1);
System.out.println(plusDays); //2021-03-03
LocalDate minusDays = now.minusDays(1);
System.out.println(minusDays);//2021-03-01
LocalDate pastDate = now.minus(2, ChronoUnit.DECADES);
System.out.println(pastDate);//2001-03-02
LocalDate plus = now.plus(2, ChronoUnit.DAYS);
System.out.println(plus);//2021-03-04
//注意:LocalDate是不可变的,因此无法更改。 任何返回LocalDate的方法都返回LocalDate的新实例。
}
LocalDate 与 Date的转换
@Test
void testLocalDate4() {
Date date = new Date();
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
LocalDate localDate = LocalDate.ofInstant(instant, zoneId);
System.out.println(localDate); //2021-03-03
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
LocalDate localDate2 = localDateTime.toLocalDate();
System.out.println(localDate2);//2021-03-03
}
@Test
void testLocalDate5() {
// LocalDate 转 Date
LocalDate localDate = LocalDate.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
Date date = Date.from(instant);
System.out.println(date);//Wed Mar 03 00:00:00 CST 2021
}
LocalDate 与 Instant的转换
@Test
void testLocalDate6() {
//Instant 转 LocalDate
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
Instant now = Instant.now();
System.out.println(now);//2021-03-03T12:31:29.568519200Z
LocalDate localDate = LocalDate.ofInstant(now, zoneId);
System.out.println(localDate);//2021-03-03
}
@Test
void testLocalDate7() {
//LocalDate 转 Instant
ZoneId zone = ZoneId.systemDefault();
LocalDate now = LocalDate.now();
System.out.println(now);//2021-03-03
Instant instant = LocalDate.now().atStartOfDay().atZone(zone).toInstant();
System.out.println(instant);//2021-03-02T16:00:00Z
}
LocalDate 详解
当我们调用LocalDate.now()
的时候我们会返回系统当前时区的一个日期, 从源码中就可以看出来
//-----------------------------------------------------------------------
/**
* Obtains the current date from the system clock in the default time-zone.
* <p>
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
* time-zone to obtain the current date.
* <p>
* Using this method will prevent the ability to use an alternate clock for testing
* because the clock is hard-coded.
*
* @return the current date using the system clock and default time-zone, not null
*/
public static LocalDate now() {
return now(Clock.systemDefaultZone());
}
LocalTime类
创建LocalTime的方式
@Test
void testLocalTime1() {
LocalTime localTime = LocalTime.now();
System.out.println(localTime);
LocalTime time = LocalTime.of(1, 30, 20);
System.out.println(time);//01:30:20
}
LocalTime 获取时,分,秒
@Test
void testLocalTime2() {
LocalTime localTime = LocalTime.now();
System.out.println(localTime);//21:18:19.843617500
int hour = localTime.getHour();
int minute = localTime.getMinute();
int second = localTime.getSecond();
System.out.println(hour);//21
System.out.println(minute);//18
System.out.println(second);//19
}
LocalTime的加减操作
@Test
void testLocalTime3() {
LocalTime localTime = LocalTime.now();
System.out.println(localTime);//21:26:15.524736600
System.out.println(localTime.plus(1, ChronoUnit.HOURS));//22:26:15.524736600
System.out.println(localTime.plusHours(1));//22:26:15.524736600
System.out.println(localTime.plusMinutes(2));//21:28:15.524736600
System.out.println(localTime.minus(1,ChronoUnit.HOURS));//20:26:15.524736600
System.out.println(localTime.minusSeconds(1));//21:26:14.524736600
}
LocalTime 与 Date的转换
@Test
void testLocalTime4(){
//Date 转 LocalTime
Date date = new Date();
System.out.println(date);//Thu Mar 04 19:53:57 CST 2021
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
LocalTime localTime = localDateTime.toLocalTime();
System.out.println(localTime);//19:53:57.089
}
@Test
void testLocalTime5() {
//LocalTime 转 Date
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
System.out.println(localTime);//19:55:14.254197800
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
System.out.println(date);//Thu Mar 04 19:55:14 CST 2021
}
LocalTime 与 Instant的转换
@Test
void testLocalTime6() {
//Instant 转 LocalTime
Instant instant = Instant.now();
System.out.println(instant);//2021-03-04T12:30:28.125689400Z
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
LocalTime localTime = localDateTime.toLocalTime();
System.out.println(localTime);//20:30:28.125689400
}
@Test
void testLocalTime7() {
//LocalTime 转 Instant
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
System.out.println(localTime);//19:55:14.254197800
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
System.out.println(instant);//2021-03-04T12:30:48.286638100Z
}
LocalTime 详解
当我们调用LocalTime.now()
的时候我们会返回系统当前时区的一个时间, 从源码中就可以看出来
//-----------------------------------------------------------------------
/**
* Obtains the current time from the system clock in the default time-zone.
* <p>
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
* time-zone to obtain the current time.
* <p>
* Using this method will prevent the ability to use an alternate clock for testing
* because the clock is hard-coded.
*
* @return the current time using the system clock and default time-zone, not null
*/
public static LocalTime now() {
return now(Clock.systemDefaultZone());
}
LocalDateTime类
LocalDateTime
类是一个没有时区的日期时间的构建。 下表显示了LocalDateTime
中一些重要的方法。 这些方法类似于LocalDate
的方法,以及用于修改时间部分的一些其他方法,例如在LocalDate
中不可用的plusHours
,plusMinutes
和plusSeconds
。
方法 | 描述 |
---|---|
now | 返回当前日期和时间的静态方法。 |
of | 从指定年份,月份,日期,小时,分钟,秒和毫秒创建LocalDateTime的静态方法。 |
getYear, getMonthValue, getDayOfMonth, getHour, getMinute, getSecond | 以int形式返回此LocalDateTime的年,月,日,小时,分钟或秒部分。 |
plusDays, minusDays | 给当前LocalDateTime添加或减去指定的天数。 |
plusWeeks, minusWeeks | 给当前LocalDateTime添加或减去指定的周数。 |
plusMonths, minusMonths | 给当前LocalDateTime添加或减去指定的月数。 |
plusYears, minusYears | 给当前LocalDateTime添加或减去指定的年数。 |
plusHours, minusHours | 给当前LocalDateTime添加或减去指定的小时数 |
plusMinutes, minusMinutes | 给当前LocalDateTime添加或减去指定的分钟数 |
plusSeconds, minusSeconds | 给当前LocalDateTime添加或减去指定的秒数 |
IsAfter, isBefore | 检查此LocalDateTime是否在指定的日期时间之后或之前 |
withDayOfMonth | 返回此LocalDateTime的拷贝,并将月份中的某天设置为指定值 |
withMonth, withYear | 返回此LocalDateTime的拷贝,其月或年设置为指定值 |
withHour, withMinute, withSecond 返回此LocalDateTime的拷贝,其小时/分钟/秒设置为指定值
LocalDateTime的创建方式
@Test
void testLocalDateTime1() {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);//2021-03-04T21:10:08.697760700
LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
System.out.println(dateTime);//2021-03-14T05:20
}
LocalDateTime获取年,月,日,小时,分钟或秒
@Test
void testLocalDateTime2() {
LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
System.out.println(dateTime);//2021-03-14T05:20
System.out.println(dateTime.getYear());//2021
System.out.println(dateTime.getMonthValue());//3
System.out.println(dateTime.getHour());//5
System.out.println(dateTime.getMinute());//20
System.out.println(dateTime.getSecond());//0
}
LocalDateTime的加减操作
@Test
void testLocalDateTime3() {
LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
System.out.println(dateTime);//2021-03-14T05:20
System.out.println(dateTime.plusDays(1).plusMinutes(1).plusMonths(1).plus(1,ChronoUnit.SECONDS));//2021-04-15T05:21:01
System.out.println(dateTime.minus(1, ChronoUnit.DAYS).minusSeconds(1).minusHours(1).minusMonths(1));//2021-02-13T04:19:59
}
LocalDateTime 与 Date的转换
@Test
void testLocalDateTime4() {
// LocalDateTime 转 Date
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); //2021-03-04T23:35:28.661442800
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
System.out.println(date);//Thu Mar 04 23:35:28 CST 2021
}
@Test
void testLocalDateTime5() {
// Date 转 LocalDateTime
java.util.Date date = new java.util.Date();
System.out.println(date); //Thu Mar 04 23:36:23 CST 2021
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
System.out.println(localDateTime);//2021-03-04T23:36:23.589
}
LocalDateTime 与 Instant的转换
@Test
void testLocalDateTime6() {
// LocalDateTime 转 Instant
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); //2021-03-07T16:23:30.639903200
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
System.out.println(instant);//2021-03-07T08:23:30.639903200Z
}
@Test
void testLocalDateTime7() {
// Instant 转 LocalDateTime
Instant instant = Instant.now();
System.out.println(instant); //2021-03-07T08:23:43.286203600Z
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
System.out.println(localDateTime);//2021-03-07T16:23:43.286203600
}
Period类
方法 | 描述 |
---|---|
between | 在两个LocalDates之间创建一个Period示例 |
ofDays, ofWeeks, ofMonths, ofYears | 创建代表给定天数/周/月/年的Period实例 |
of | 根据给定的年数,月数和天数创建一个Period实例 |
getDays, getMonths, getYears | 以int形式返回此Period的天数/月/年 |
isNegative | 如果此Period的三个部分中的任何一个为负数,则返回true。 否则返回false |
isZero | 如果此Period的所有三个部分均为零,则返回true。 否则,返回false |
plusDays, minusDays | 在此Period上添加或减去给定的天数 |
plusMonths, minusMonths | 在此Period上增加或减去给定的月数 |
plusYears, minusYears | 在此Period增加或减去给定的年数 |
withDays | 以指定的天数返回此Period的拷贝 |
withMonths | 以指定的月数返回此Period的拷贝 |
withYears | 以指定的年数返回此Period的拷贝 |
创建Period的方式
创建一个Period
很简单,between,of,ofDays
/ ofWeeks
/ ofMonths
/ ofYears
等静态工厂方法可以很简单帮我们创建Period
。
@Test
void testPeriodTest1() {
//创建代表两周的Period实例
Period twoWeeks = Period.ofWeeks(2);
System.out.println(twoWeeks);//P14D
//创建代表一年两个月三天的Period实例
Period p = Period.of(1, 2, 3);
System.out.println(p);//P1Y2M3D
}
Period获取某个期间的年/月/日组件
@Test
void testPeriodTest2() {
//创建代表两周的Period实例
Period twoWeeks = Period.ofWeeks(2);
System.out.println(twoWeeks);//P14D
System.out.println(twoWeeks.getDays());//14
Period twoYears = Period.ofYears(2);
System.out.println(twoYears);//P2Y
System.out.println(twoYears.getYears());//2
Period twoMonths = Period.ofMonths(2);
System.out.println(twoMonths);//P2M
System.out.println(twoMonths.getMonths());//2
}
Period的加减操作
@Test
void testPeriodTest3() {
//创建代表两周的Period实例
Period twoWeeks = Period.ofWeeks(2);
System.out.println(twoWeeks);//P14D
System.out.println(twoWeeks.getDays());//14
Period plusDays = twoWeeks.plusDays(1);
System.out.println(plusDays.getDays());//15
Period minusDays = plusDays.minusDays(2);
System.out.println(minusDays.getDays());//13
}
年龄计算器
@Test
void testPeriodTest4() {
LocalDate dateA = LocalDate.of(1978, 8, 26);
LocalDate dateB = LocalDate.of(1988, 9, 28);
Period period = Period.between(dateA, dateB);
System.out.printf("Between %s and %s"
+ " there are %d years, %d months"
+ " and %d days%n", dateA, dateB,
period.getYears(),
period.getMonths(),
period.getDays());//Between 1978-08-26 and 1988-09-28 there are 10 years, 1 months and 2 days
}
ZonedDateTime类
ZonedDateTime
类以一个时区为日期时间的构建。
ZonedDateTime
始终是不可变的,时间分量的存储精度为纳秒。
ZonedDateTIme
中一些重要方法的使用与LocalDateTime类似,只是多了一个时区的概念。
ZonedDateTime 创建方式
@Test
void testZonedDateTime1() {
//无参now方法会使用计算机的默认时区创建ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);//2021-03-07T20:56:15.409935300+08:00[Asia/Shanghai]
//允许传递区域标识符
ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(parisTime);//2021-03-07T13:56:15.411934400+01:00[Europe/Paris]
ZonedDateTime time = ZonedDateTime.of(2021, 3, 4, 2, 2, 2, 2, ZoneId.systemDefault());
System.out.println(time);//2021-03-04T02:02:02.000000002+08:00[Asia/Shanghai]
ZonedDateTime dateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Europe/Paris"));
System.out.println(dateTime);//2021-03-07T20:56:15.414933100+01:00[Europe/Paris]
ZonedDateTime zonedDateTime1 = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.of("Europe/Paris"));
System.out.println(zonedDateTime1);//2021-03-07T20:56:15.414933100+01:00[Europe/Paris]
}
查看所有的时区:
@Test
void testZonedDateTimeTest2() {
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for (String availableZoneId : availableZoneIds) {
System.out.println(availableZoneId);
}
}
ZonedDateTime 的加减操作
@Test
void testZonedDateTime3() {
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);//2021-03-07T21:00:39.707036800+08:00[Asia/Shanghai]
System.out.println(zonedDateTime.plusDays(1));//2021-03-08T21:00:39.707036800+08:00[Asia/Shanghai]
System.out.println(zonedDateTime.minus(1, ChronoUnit.DAYS));//2021-03-06T21:00:39.707036800+08:00[Asia/Shanghai]
}
Duration 类
Duration
类是基于时间的持续时间的构建。 它与Period
类似,不同之处在于Duration
的时间分量为纳秒精度,并考虑了ZonedDateTime
实例之间的时区.
方法 | 描述 |
---|---|
between | 在两个时差的对象之间创建一个Duration实例,例如在两个LocalDateTime或两个ZonedDateTime之间。 |
ofYears, ofMonths, ofWeeks, ofDays, ofHours, ofMinutes, ofSeconds, ofNano | 创建给定年数/月/周/天/小时/分钟/秒/纳秒的Duration实例 |
of | 根据指定数量的时间单位创建Duration实例 |
toDays, toHours, toMinutes | 以int形式返回此Duration的天数/小时/分钟数 |
isNegative | 如果此Duration为负,则返回true。 否则返回false。 |
isZero | 如果此Duration长度为零,则返回true。 否则,返回false |
plusDays, minusDays | 在此Duration内添加或减去指定的天数。 |
plusMonths, minusMonths | 在此Duration内添加或减去指定的月数。 |
plusYears, minusYears | 在Duration内添加或减去指定的年数 |
withSeconds | 以指定的秒数返回此Duration的拷贝。 |
Duration 的创建方式
可以通过调用静态方法between或of来创建Duration
@Test
void testDuration1() {
LocalDateTime dateTimeA = LocalDateTime
.of(2015, 1, 26, 8, 10, 0, 0);
LocalDateTime dateTimeB = LocalDateTime
.of(2015, 1, 26, 11, 40, 0, 0);
Duration duration = Duration.between(
dateTimeA, dateTimeB);
System.out.printf("There are %d hours and %d minutes.%n",
duration.toHours(),
duration.toMinutes() % 60);//There are 3 hours and 30 minutes.
}
两个ZoneDateTime
之间创建一个Duration
,具有相同的日期和时间,但时区不同。
@Test
void testDuration2() {
//相同时间 不同时区
ZonedDateTime zdt1 = ZonedDateTime.of(
LocalDateTime.of(2015, Month.JANUARY, 1,
8, 0),
ZoneId.of("America/Denver"));
ZonedDateTime zdt2 = ZonedDateTime.of(
LocalDateTime.of(2015, Month.JANUARY, 1,
8, 0),
ZoneId.of("America/Toronto"));
Duration duration = Duration.between(zdt1, zdt2);
System.out.printf("There are %d hours and %d minutes.%n",
duration.toHours(),
duration.toMinutes() % 60);//There are -2 hours and 0 minutes.
}
DateTimeFormatter 类
@Test
void testDateTimeFormatter() {
LocalDate localDate = LocalDate.of(2019, 9, 10);
String format = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(format);//20190910
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String format2 = localDate.format(dateTimeFormatter);
System.out.println(format2);//10/09/2019
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
LocalDateTime parse = LocalDateTime.parse("2017-04-01 22:39:40", timeFormatter);
System.out.println(parse);//2017-04-01T22:39:40
}
参考
java 8新特性 instant 和 LocalDateTime
LocalDateTime,String,Instant相互转换
Java8学习笔记:LocalDateTime、Instant 和 OffsetDateTime 相互转换
java中的时间与时区:LocalDateTime和Date
Java面试问题总结——为什么处理时间问题建议使用LocalDate类而逐渐抛弃Date类?