前言
只在JAVA8之前,我们常用的时间API一般就是Date,Calendar类,但我们都知道这些类是线程不安全的,而且有时候使用起来也不是很简洁,所以,JAVA8在java.time包出了新的日期时间API。
API
java.time包主要有以下类型:
本地日期和时间:LocalDateTime,LocalDate,LocalTime;
带时区的日期和时间:ZonedDateTime;
时刻:Instant;
时区:ZoneId,ZoneOffset;
时间间隔:Duration。
注意:使用旧的Date对象时,我们用SimpleDateFormat进行格式化显示。使用新的LocalDateTime或ZonedLocalDateTime时,我们要进行格式化显示,就要使用DateTimeFormatter。
创建DateTimeFormatter,使用ofPattern方法,传入格式即可,而且DateTimeFormatter也是线程安全的不可变对象
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
主要枚举类:
DayOfWeek
星期枚举类,如“星期二”。
Month
月份枚举类,如“七月”。
这些新的API类基本都是使用final修饰,不可变的。所以它们也是线程安全的。
日期和时间类简介
Instant本质上是一个数字时间戳。 当前Instant可以从Clock检索 。 这对于一个时间点的记录和持久性是有用的,并且在过去已经与存储System.currentTimeMillis()的结果相关联 。
LocalDate存储没有时间的日期。 它存储一个像“2010-12-03”这样的日期,可以用来存储一个生日。
LocalTime存储没有日期的时间。 这样可以储存一个像“11:30”这样的时间,可以用来存储一个开或关的时间。
LocalDateTime存储日期和时间。 这样可以存储像2010-12-03T11:30这样的日期。
ZonedDateTime存储具有时区的日期和时间。 如果您想要考虑到ZoneId (如“欧洲/巴黎”)的日期和时间的精确计算,这是有用的。 在可能的情况下,建议在没有时区的情况下使用更简单的类。 时区的广泛使用往往会增加应用程序的相当大的复杂性。
LocalDateTime可以看作是由LocalDate和LocalTime组成的
下面,我主要介绍LocalDate和LocalTime的API
LocalDate
LocalDate是一个不可变的日期时间对象,表示日期,没有带时分秒的,通常被视为年月日。 也可以访问其他日期字段,例如日期,星期几和星期。 例如,值“2007年10月2日”可存储在LocalDate 。
该类不存储或表示时间或时区。 相反,它是日期的描述,用于生日。 它不能代表时间线上的即时信息,而没有附加信息,如偏移或时区。
如:
LocalDate.now()
输出:2020-06-16
LocalDate常用方法
now():从默认时区的系统时钟获取当前日期,这将查询默认时区中的system clock以获取当前日期。
now(ZoneId zone):从指定时区的系统时钟获取当前日期。zone - 要使用的区域ID,不为空
of(int year,Month month,int dayOfMonth):这将返回一个LocalDate与指定的年,月和日。 该日期必须在年和月中有效,否则将抛出异常。
例:LocalDate of = LocalDate.of(2020, 06, 16);
ofYearDay(int year,int dayOfYear):这将返回一个LocalDate与指定年份和日期。 年份必须在一年中有效,否则将被抛出异常。
参数
year - 从MIN_YEAR到MAX_YEAR的年份
dayOfYear - 代表从1到366的日期
from(TemporalAccessor temporal):这将基于指定的时间获取本地日期。
parse(CharSequence text):从一个文本字符串获取一个LocalDate的实例
参数
text - 要解析的文本,如“2017-12-03”,不为空
以上都是LocalDate的静态方法,直接使用LocalDate调用
下面是LocalDate的非静态方法
public int getYear():获取年份字段,此方法返回一年的int值int值。
public Month getMonth():返回Month枚举的月份字段。
public int getMonthValue():获取月份值
public int getDayOfMonth():返回月份中的第几天,1到31日
public int getDayOfYear():返回该LocalDate属于一年的第几天,1到365日
public DayOfWeek getDayOfWeek():返回LocalDate属于星期几,返回的是DayOfWeek 枚举类对象,可以通过getValue获取值
例
LocalDate of = LocalDate.of(2020, 06, 16);
System.out.println(dayOfWeek);
System.out.println(dayOfWeek.getValue());
输出结果:
TUESDAY
2
public int lengthOfMonth():返回由此日期表示的月份的长度,例如,1月份的日期将返回31。
public int lengthOfYear():返回由此日期表示的年份的长度。365或366
public LocalDate withYear(int year):返回此日期的副本,并更改年份。此实例是不可变的,不受此方法调用的影响。
public LocalDate withMonth(int month):返回这个日期的副本,并更改月份。
public LocalDate withDayOfMonth(int dayOfMonth):返回此日期的副本,并更改日期。 如果生成的日期无效,则抛出异常。
with方法例子:
//每个LocalDate对象都是不可变的,所以更改需要使用新对象
LocalDate of = LocalDate.of(2020, 06, 16);
LocalDate date = of.withYear(2019);
LocalDate date1 = of.withMonth(10);
LocalDate date2 = of.withYear(2020).withMonth(10);
System.out.println(date);
System.out.println(date1);
输出:
2019-06-16
2020-10-16
public LocalDate plus(long amountToAdd,TemporalUnit unit):返回此日期的副本,并添加指定单位的数值。
public LocalDate plusYears(long yearsToAdd):返回这个LocalDate的副本,添加指定的年数。
public LocalDate plusMonths(long monthsToAdd):返回这个LocalDate的副本,添加指定的月份。
public LocalDate plusWeeks(long weeksToAdd):返回这个LocalDate的副本,并以添加指定的周数。
public LocalDate plusDays(long daysToAdd):返回添加指定天数的LocalDate的副本。
对LocalDate进行减去,都是使用minus,如minusYears,minusMonths等,与相加差不多
public LocalDate minusYears(long yearsToSubtract):返回此LocalDate的副本,减去的指定的年份。
public LocalDateTime atTime(LocalTime time):结合此日期与时间创建一个LocalDateTime 。
例:
LocalDate of = LocalDate.of(2020, 06, 16);
LocalDateTime localDateTime = of.atTime(LocalTime.now());
System.out.println(localDateTime);
输出:
2020-06-16T11:14:25.660941300
public LocalDateTime atTime(int hour, int minute, int second):返回一个LocalDateTime从该日期在指定的小时,分钟和秒来形成。
参数
hour - 从0到23的使用时间
minute - 从0到59使用的小时
second - 从0到59的秒表示
public LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond):返回一个LocalDateTime在指定的时,分,秒和纳秒从该日期形成。
参数
hour - 从0到23的使用时间
minute - 从0到59使用的小时
second - 从0到59的秒表示
nanoOfSecond - 表示从0到999,999,999的纳秒
public LocalDateTime atStartOfDay():返回一个此日期的午夜00:00时LocalDateTime对象 。
例:
LocalDate now = LocalDate.now();
System.out.println(now.atStartOfDay());
输出:
2020-06-16T00:00
public int compareTo(ChronoLocalDate other):比较两个日期,如果年份不相等,则比较年份。年份相等,月份不相等,则比较月份。年月相等,则比较日期。大为正,小为负
例:now时间为2020-06-16
LocalDate now = LocalDate.now();
LocalDate of = LocalDate.of(2020, 06, 14);
System.out.println(now.compareTo(of));
输出
2
我们可以看一下LocalDate使用的比较方法源码,就明白是怎么比较的了
int compareTo0(LocalDate otherDate) {
int cmp = (year - otherDate.year);
if (cmp == 0) {
cmp = (month - otherDate.month);
if (cmp == 0) {
cmp = (day - otherDate.day);
}
}
return cmp;
}
public boolean isAfter(ChronoLocalDate other):检查此日期是否在指定日期之后。如果此日期在指定日期之后,则为true。
public boolean isBefore(ChronoLocalDate other):检查此日期是否在指定日期之前。只比较类型为LocalDate对象,其他类型返回false
public boolean isEqual(ChronoLocalDate other):检查此日期是否等于指定的日期。如果不是LocalDate类型,会使用ChronoLocalDate父类的isEqual方法
源码如下:
public boolean isEqual(ChronoLocalDate other) {
if (other instanceof LocalDate) {
return compareTo0((LocalDate) other) == 0;
}
return ChronoLocalDate.super.isEqual(other);
}
public boolean equals(Object obj):检查这个日期是否等于另一个日期。只比较类型为LocalDate对象,其他类型返回false。
源码如下:
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LocalDate) {
return compareTo0((LocalDate) obj) == 0;
}
return false;
}