创建和管理基于日期和基于时间的事件,包括使用LocalDate、LocalTime、LocalDateTime、Instant、Period和Duration将日期和时间组合到单个对象中。
使用Instant、Period、Duration和TemporalUnit定义、创建和管理基于日期和基于时间的事件。

新的Date/Time API

image.png
java8引入了一个新的日期/时间 API,该 API 基于流行的date/time库joda-Time,并包含在新的 Java.Time 包中。
image.png
image.png

Java原有的Date和Calendar

Java原有的时间和日期类java.util.Datejava.util.Calendar存在的问题

  • java.util.Date表示毫秒精度的时间(在某些应用程序中这可能不够)。年份从1900年开始,月份从0开始
  • 日期的时区是 JVM 的默认时区
  • java.util.Date和java.util.Calendar都是可变的类,这意味着当它们发生变化时,它们不会用新的值创建另一个实例(新的函数式编程必须要使用final)

核心类

  • 所有这些类都是不可变的final、线程安全的,除了 Instant 以外,它们不存储或表示时区。

实现java.time.temporal.Temporal接口的类

  • LocalDate
    包含年、月和月日信息的日期。例如,2015-08-25。
  • LocalTime
    包含小时、分钟、秒和纳秒信息的时间。如13:21.05.123456789
  • LocalDateTime
  • LocalDate和LocalTime两者的组合。例如,2015-08-2513:21.05.12345

实现java.time.temporal.TemporalAmount接口的类

  • Instant
    以秒和纳秒为单位的单个时间点,例如923,456,789秒和186,054,812纳秒
  • Period
    以年、月和天为单位的时间量。例如,5年2个月零9天。
  • Duration
    持续时间表示以秒和纳秒表示的时间量。例如,12.87656秒。

LocalDate 类

它保存了日期的年、月、日和派生信息。它的所有方法都使用这些信息或者有一个版本来处理每个方法。

常用方法

  • 创建一个实例
    使用静态static方法
// With year(-999999999 to 999999999),
// month (1 to 12), day of the month (1 - 31)}
LocalDate newYear2001 = LocalDate.of(2001, 1, 1);
// This version uses the enum java.time.Month
LocalDate newYear2002 = LocalDate.of(2002, Month.JANUARY, 1);

该类月份是1-12。而不是像java.util.Date从0开始
如果尝试创建具有无效值的日期(如2月29日) ,则会引发异常。
image.png

  • 获得实例的年月日
int year = today.getYear();
int month = today.getMonthValue();
Month monthAsEnum = today.getMonth(); // as an enum
int dayYear = today.getDayOfYear();
int dayMonth = today.getDayOfMonth();
DayOfWeek dayWeekEnum = today.getDayOfWeek(); //as an enum

因为其实现Temporal接口

int get(java.time.temporal.TemporalField field) // value as int
long getLong(java.time.temporal.TemporalField field) // value as long
int year = today.get(ChronoField.YEAR);
int month = today.get(ChronoField.MONTH_OF_YEAR);
int dayYear = today.get(ChronoField.DAY_OF_YEAR);
int dayMonth = today.get(ChronoField.DAY_OF_MONTH);
int dayWeek = today.get(ChronoField.DAY_OF_WEEK);
long dayEpoch = today.getLong(ChronoField.EPOCH_DAY);

生成新的LocalDate实例

一旦创建了这个类的实例,我们就不能修改它,但是我们可以从现有的实例中创建另一个实例。

  • 使用with方法
LocalDate newYear2003 = newYear2001.with(ChronoField.YEAR, 2003);
LocalDate newYear2004 = newYear2001.withYear(2004);
LocalDate december2001 = newYear2001.withMonth(12);
LocalDate february2001 = newYear2001.withDayOfYear(32);
// Since these methods return a new instance, we can chain them!
LocalDate xmas2001 = newYear2001.withMonth(12).withDayOfMonth(25);
  • 通过加或减年,月,天,周
// Adding
LocalDate newYear2005 = newYear2001.plusYears(4);
LocalDate march2001 = newYear2001.plusMonths(2);
LocalDate january15_2001 = newYear2001.plusDays(14);
LocalDate lastWeekJanuary2001 = newYear2001.plusWeeks(3);
LocalDate newYear2006 = newYear2001.plus(5, ChronoUnit.YEARS); 

// Subtracting
LocalDate newYear2000 = newYear2001.minusYears(1);
LocalDate nov2000 = newYear2001.minusMonths(2);
LocalDate dec30_2000 = newYear2001.minusDays(2);
LocalDate lastWeekDec2001 = newYear2001.minusWeeks(1);
LocalDate newYear1999 = newYear2001.minus(2, ChronoUnit.YEARS);

加减版本采用 java. time.temporal.ChronoUnit 枚举,与 java.time.temporal.ChronoField 不同

toString

toString ()以 yyyy-mm-dd 格式返回日期

System.out.println(newYear2001.toString()); // Prints 2001-01-01

LocalTime类

包含了小时、分钟、秒和纳秒。它的所有方法都使用或处理这些信息。

常用方法

类似LocalDate 的相同(或非常相似)方法,但适用于使用时间而不是日期。

创建一个实例

  • 静态方法
// With hour (0-23) and minutes (0-59)
LocalTime fiveThirty = LocalTime.of(5, 30);
// With hour, minutes, and seconds (0-59)
LocalTime noon = LocalTime.of(12, 0, 0);
// With hour, minutes, seconds, and nanoseconds (0-999,999,999)
LocalTime almostMidnight = LocalTime.of(23, 59, 59, 999999);
  • 创建一个具有无效值的时间(如 LocalTime.of (24,0)) ,则会引发异常。要获取当前时间,请使用 now () :

生成新的LoaclTime

  • 使用with方法
    image.png
 LocalTime with = noon.with(MONTH_OF_YEAR, 22);
LocalTime ten = noon.with(ChronoField.HOUR_OF_DAY, 10);
LocalTime eight = noon.withHour(8);
LocalTime twelveThirty = noon.withMinute(30);
LocalTime thirtyTwoSeconds = noon.withSecond(32);
// Since these methods return a new instance, we can chain them!
LocalTime secondsNano = noon.withSecond(20).withNano(999999);
  • 加减小时、分、秒或纳秒
// Adding
LocalTime sixThirty = fiveThirty.plusHours(1);
LocalTime fiveForty = fiveThirty.plusMinutes(10);
LocalTime plusSeconds = fiveThirty.plusSeconds(14);
LocalTime plusNanos = fiveThirty.plusNanos(99999999);
LocalTime sevenThirty = fiveThirty.plus(2, ChronoUnit.HOURS);

// Subtracting
LocalTime fourThirty = fiveThirty.minusHours(1);
LocalTime fiveTen = fiveThirty.minusMinutes(20);
LocalTime minusSeconds = fiveThirty.minusSeconds(2);
LocalTime minusNanos = fiveThirty.minusNanos(1);
LocalTime fiveTwenty = fiveThirty.minus(10, ChronoUnit.MINUTES);

LocalDateTime类

结合了 LocalDate 和 LocalTime 类

创建实例

要创建一个实例,我们可以使用静态方法() ,也可以使用 LocalDate 或 LocalTime 实例:

// Setting seconds and nanoseconds to zero
LocalDateTime dt1 = LocalDateTime.of(2014, 9, 19, 14, 5);
// Setting nanoseconds to zero
LocalDateTime dt2 = LocalDateTime.of(2014, 9, 19, 14, 5, 20);
// Setting all fields
LocalDateTime dt3 = LocalDateTime.of(2014, 9, 19, 14, 5, 20, 9);
// Asumming this date
LocalDate date = LocalDate.now();
// And this time
LocalTime time = LocalTime.now();
// Combine the above date with the given time like this
LocalDateTime dt4 = date.atTime(14, 30, 59, 999999);
// Or this LocalDateTime dt5 = date.atTime(time);
// Combine this time with the given date. Notice that LocalTime
// only has this method to be combined with a LocalDate
LocalDateTime dt6 = time.atDate(date);

生成一个新的实例

  • 使用with
LocalDateTime dt7 = now.with(ChronoField.HOUR_OF_DAY, 10);
LocalDateTime dt8 = now.withMonth(8);
// Since these methods return a new instance, we can chain them!
LocalDateTime dt9 = now.withYear(2013).withMinute(0);
  • 加减年、月、日、周、小时、分、秒或纳秒
// Adding
LocalDateTime dt10 = now.plusYears(4);
LocalDateTime dt11 = now.plusWeeks(3);
LocalDateTime dt12 = newYear2001.plus(2, ChronoUnit.HOURS);

// Subtracting
LocalDateTime dt13 = now.minusMonths(2);
LocalDateTime dt14 = now.minusNanos(1);
LocalDateTime dt15 = now.minus(10, ChronoUnit.SECONDS);

Instant类

自从某一个时刻以来已经过去的秒数中的一个瞬间,这是 UNIX/POSIX 系统中使用的约定,设置在 UTC 时间1970年1月1日
自初始时刻时间以每天86,400秒计算。此信息存储为。该类还支持纳秒级精度,以 int 形式存储

创建实例

  • 静态static的of方法
// Setting seconds
Instant fiveSecondsAfterEpoch = Instant.ofEpochSecond(5);
// Setting seconds and nanoseconds (can be negative)
Instant sixSecTwoNanBeforeEpoch = Instant.ofEpochSecond(-6, -2);
// Setting milliseconds after (can be before also) epoch
Instant fifthyMilliSecondsAfterEpoch = Instant.ofEpochMilli(50);

image.png

  • now
Instant now = Instant.now();

生成新的Instant

  • 通过with
Instant i1 = now.with(ChronoField.NANO_OF_SECOND, 10);
  • 增加或减少秒、毫秒或纳秒
// Adding
Instant dt10 = now.plusSeconds(400);
Instant dt11 = now.plusMillis(98622200);
Instant dt12 = now.plusNanos(3000138900);
Instant dt13 = newYear2001.plus(2, ChronoUnit.MINUTES);

// Subtracting
Instant dt14 = now.minusSeconds(2);
Instant dt15 = now.minusMillis(1);
Instant dt16 = now.minusNanos(1);
Instant dt17 = now.minus(10, ChronoUnit.SECONDS);

Period类

以年、月和天为单位的时间段

创建实例

// Setting years, months, days (can be negative)
Period period5y4m3d = Period.of(5, 4, 3);
// Setting days (can be negative), years and months will be zero
Period period2d = Period.ofDays(2);
// Setting months (can be negative), years and days will be zero
Period period2m = Period.ofMonths(2);
// Setting weeks (can be negative). The resulting period will
// be in days (1 week = 7 days). Years and months will be zero
Period period14d = Period.ofWeeks(2);
// Setting years (can be negative), days and months will be zero
Period period2y = Period.ofYears(2);
LocalDate march2003 = LocalDate.of(2003, 3, 1);
LocalDate may2003 = LocalDate.of(2003, 5, 1);
Period dif = Period.between(march2003, may2003); // 2 months

输出如下
image.png
image.png

  • 计算方法
    1.首先计算完整的月份,然后计算剩余的天数。然后把月份的数量分成年份(1年等于12个月)。如果一个月的结束日大于或等于该月的开始日,则考虑该月。
    2.如果结束在开始之前(年、月和日将有一个负号) ,则此方法的结果可能是一个负周期。
// dif1 will be 1 year 2 months 2 days
Period dif1 = Period.between( LocalDate.of(2000, 2, 10), LocalDate.of(2001, 4, 12));
// dif2 will be 25 days
Period dif2 = Period.between( LocalDate.of(2013, 5, 9), LocalDate.of(2013, 6, 3));
// dif3 will be -2 years -3 days
Period dif3 = Period.between( LocalDate.of(2014, 11, 3), LocalDate.of(2012, 10, 31));

生成新的Period

  • 使用with方法
Period period8d = period2d.withDays(8);
// Since these methods return a new instance, we can chain them!
Period period2y1m2d = period2d.withYears(2).withMonths(1);
  • 加减年、月或日
// Adding
Period period9y4m3d = period5y4m3d.plusYears(4);
Period period5y7m3d = period5y4m3d.plusMonths(3);
Period period5y4m6d = period5y4m3d.plusDays(3);
Period period7y4m3d = period5y4m3d.plus(period2y);

// Subtracting
Period period5y4m3d = period5y4m3d.minusYears(2);
Period period5y4m3d = period5y4m3d.minusMonths(1);
Period period5y4m3d = period5y4m3d.minusDays(1);
Period period5y4m3d = period5y4m3d.minus(period2y);

toString

toString ()以 PNYNMND 格式返回

System.out.println(period5y4m3d.toString()); // Prints P5Y4M3D

Duration类

类类似于 Period 类,唯一的特点是它以秒和纳秒表示时间

创建实例

Duration oneDay = Duration.ofDays(1); // 1 day = 86400 seconds
Duration oneHour = Duration.ofHours(1); // 1 hour = 3600 seconds
Duration oneMin = Duration.ofMinutes(1); // 1 minute = 60 seconds
Duration tenSeconds = Duration.ofSeconds(10);
// Set seconds and nanoseconds (if they are outside the range
// 0 to 999,999,999, the seconds will be altered, like below)
Duration twoSeconds = Duration.ofSeconds(1, 1000000000);
// Seconds and nanoseconds are extracted from the passed milisecs
Duration oneSecondFromMilis = Duration.ofMillis(2);
// Seconds and nanoseconds are extracted from the passed nanos
Duration oneSecondFromNanos = Duration.ofNanos(1000000000);
Duration oneSecond = Duration.of(1, ChronoUnit.SECONDS);

总结

  • LocalDate、LocalTime、LocalDateTime、Instant、Period、Duration是Java.Time包中新的Java日期/时间API的核心类。它们是不可变的,线程安全的,除了Instant之外,它们不存储或表示时区。
  • LocalDate、LocalTime、LocalDateTime和Instant实现了java.time.temporal.temporal接口,因此它们都有相似的方法。而Period和Duration实现接口java.time.temporal.TemporalAmount,这也使得它们非常相似。
  • LocalDate表示包含年、月和月日信息的日期。
  • LocalTime表示包含小时、分钟、秒和纳秒信息的时间。
  • LocalDateTime是LocalDate或LocalTime的组合。
  • Instant表示以秒和纳秒为单位的单个时间点。
  • Period表示以年、月和日为单位的时间量。
  • 持续时间表示以秒和纳秒为单位的时间量。

这个家伙很懒,啥也没有留下😋