类名 | 介绍 |
---|---|
java.util.Date | 1. 这个类无法表示日期,只能以毫秒的精度表示时间。 2. 年份的起始选择是1900年,月份的起始从0开始。2014年3月18日 = Date date = new Date(114, 2, 18) 。 3. 不支持时区,但 toString() 结果确默认显示时区信息。4. 可以变的。 |
java.util.Calendar | 1. 月份依旧是从 0 开始计算。2. 可以变的。 |
java.text.DateFormat | 不是 线程安全的。 |
这些新类都位于 java.time 包下。提供了统一风格的 API。
下表所有类都实现了 Temporal 接口。
如:获取年、月、日、周、时、分、秒等方法。
接口 | 介绍 |
---|---|
java.time.temporal | 接口 。定义了如何读取和操纵为时间建模的对象的值。 |
java.time.temporal.TemporalField | 接口 。它定义了如何访问temporal对象某个字段的值。 |
java.time.chrono.ChronoLocalDate | 用于高级全球化用例的任意时间表中没有时间或时区的日期。API的设计鼓励使用LocalDate 而不是此接口,即使在应用程序需要处理多个日历系统的情况下也是如此。 |
类 | 介绍 |
---|---|
java.time.LocalDate | 日期对象 |
java.time.LocalTime | 时间对象 |
java.time.LocalDateTime | LocalDate 和 LocalTime 的合体。它表示日期和时间 但 不带时区 。可以直接创建,也可通过合并日期和时间来创建。 |
ZonedDateTime | LocalDate 、LocalTime 、时区 的合体 |
java.time.Instant | 便于机器处理,从计算机的角度,对时间建模。是一个持续时间段上某个点。以 Unix元年 (UTC时区1970年1月1日午夜时分)开始所经历的秒数。1. 可用于在应用程序中记录事件时间戳。 |
java.time.Duration | 两个时间 Temporal 对象:A 和B 之间持续的时长 。1. LocalDateTime 和 Instant 是为不同的目的而设计的,无法将二者混用计算时长 。2. 本类主要用于以 秒 和纳秒 衡量时间的长短,between 方法不支持LocalDate 做参数,因为它不带时间 。 |
java.time.Period | 此类用于计算年、月、日 之间持续的时长 。 |
java.time.temporal.ChronoField | 此枚举实现了 TemporalField 接口,所以你可以很方便地使用 get 方法得到枚举元素的值。 |
java.time.format.DateTimeFormatter | 用于打印和解析日期时间对象的格式化程序。 |
ZoneOffset | |
ZoneId |
LocalDate date = LocalDate.of(2014, 3, 18);
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
DayOfWeek dow = date.getDayOfWeek();
int len = date.lengthOfMonth();
boolean leap = date.isLeapYear();
使用工厂方法从系统时钟中获取当前的日期
LocalDate today = LocalDate.now();
2022年07月04日
int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);
LocalTime time = LocalTime.of(13, 45, 20);
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
LocalDate
和 LocalTime
都可以通过静态方法 parse
解析代表它们的字符串创建。
LocalDate date = LocalDate.parse("2022-07-04");
LocalTime time = LocalTime.parse("20:53:12");
// 2014-03-18T13:45:20
LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(13, 45, 20);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);
从 LocalDateTime中
提取 LocalDate
或者 LocalTime
组件:
LocalDate date1 = dt1.toLocalDate();
LocalTime time1 = dt1.toLocalTime();
使用 秒
和 纳秒
创建实例。以下都是:3秒
之后。
Instant.ofEpochSecond(3); // 3秒之后
Instant.ofEpochSecond(3, 0); // 3秒之后 + 0纳秒
Instant.ofEpochSecond(2, 1_000_000_000); // 2秒之后 + 10亿纳秒(1秒)
Instant.ofEpochSecond(4, -1_000_000_000); // 4秒之后 - 10亿纳秒(1秒)
分别用于表示时间
或日期
之间的时长
。
Duration threeMinutes = Duration.ofMinutes(3);
Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);
Period tenDays = Period.ofDays(10);
Period threeWeeks = Period.ofWeeks(3);
Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
Duration类和Period类共享了很多相似的方法,参见表12-1所示。
方法名 | 是否是静态方法 | 方法描述 |
---|---|---|
between | 是 | 创建两个时间点之间的 |
from | 是 | 由一个临时时间点创建 |
of | 是 | 由它的组成部分创建 |
parse | 是 | 由字符串创建 |
addTo | 否 | 创建该 |
get | 否 | 读取该 |
isNegative | 否 | 检查该 |
isZero | 否 | 检查该 |
minus | 否 | 通过减去一定的时间创建该 |
multipliedBy | 否 | 将 |
negated | 否 | 以忽略某个时长的方式创建该 |
plus | 否 | 以增加某个指定的时长的方式创建该 interval 的副本 |
subtractFrom | 否 | 从指定的 temporal 对象中减去该 interval |
LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
LocalDate date2 = date1.withYear(2011); // 2011-03-18
LocalDate date3 = date2.withDayOfMonth(25); // 2011-03-25
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9); // 2011-09-25
LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
LocalDate date2 = date1.plusWeeks(1); // 2014-03-25
LocalDate date3 = date2.minusYears(3); // 2011-03-25
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); // 2011-09-25
大概你已经猜到,像LocalDate、LocalTime、LocalDateTime以及Instant这样表示时
间点的日期时间类提供了大量通用的方法,表12-2对这些通用的方法进行了总结。
方法名 | 是否是静态方法 | 描述 |
---|---|---|
from | 是 | 依据传入的 Temporal 对象创建对象实例 |
now | 是 | 依据系统时钟创建 Temporal 对象 |
of | 是 | 由Temporal 对象的某个部分创建该对象的实例 |
parse | 是 | 由字符串创建 Temporal 对象的实例 |
atOffset | 否 | 将 Temporal 对象和某个时区偏移相结合 |
atZone | 否 | 将 Temporal 对象和某个时区相结合 |
format | 否 | 使用某个指定的格式器将 Temporal 对象转换为字符串(Instant类不提供该方法) |
get | 否 | 读取 Temporal 对象的某一部分的值 |
minus | 否 | 创建 Temporal 对象的一个副本,通过将当前 Temporal 对象的值减去一定的时长创建该副本 |
plus | 否 | 创建 Temporal 对象的一个副本,通过将当前 Temporal 对象的值加上一定的时长创建该副本 |
with | 否 | 以该 Temporal 对象为模板,对某些状态进行修改创建该对象的副本 |
import static java.time.temporal.TemporalAdjusters.*;
LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY)); // 2014-03-23
LocalDate date3 = date2.with(lastDayOfMonth()); // 2014-03-31
表12-3提供了TemporalAdjuster中包含的工厂方法列表。
方法名 | 描述 |
---|---|
dayOfWeekInMonth | 创建一个新的日期,它的值为同一个月中每一周的第几天 |
firstDayOfMonth | 创建一个新的日期,它的值为当月的第一天 |
firstDayOfNextMonth | 创建一个新的日期,它的值为下月的第一天 |
firstDayOfNextYear | 创建一个新的日期,它的值为明年的第一天 |
firstDayOfYear | 创建一个新的日期,它的值为当年的第一天 |
firstInMonth | 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值 |
lastDayOfMonth | 创建一个新的日期,它的值为当月的最后一天 |
lastDayOfNextMonth | 创建一个新的日期,它的值为下月的最后一天 |
lastDayOfNextYear | 创建一个新的日期,它的值为明年的最后一天 |
lastDayOfYear | 创建一个新的日期,它的值为今年的最后一天 |
lastInMonth | 创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值 |
next/previous | 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期 |
nextOrSame/previousOrSame | 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象 |
TemporalAdjuster
是一个 函数式接口
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
java.time.format
这个包下都是时间格式化相关的内容 。最重要的比如:DateTimeFormatter
LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18
java.util.DateFormat
相比较,所有的DateTimeFormatter
实例都是线程安全的。LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1 = LocalDate.of(2014, 3, 18);
String formattedDate = date1.format(formatter);
LocalDate date2 = LocalDate.parse(formattedDate, formatter);
DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN);
LocalDate date1 = LocalDate.of(2014, 3, 18);
String formattedDate = date.format(italianFormatter); // 18. marzo 2014
LocalDate date2 = LocalDate.parse(formattedDate, italianFormatter);
DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_MONTH)
.appendLiteral(". ")
.appendText(ChronoField.MONTH_OF_YEAR)
.appendLiteral(" ")
.appendText(ChronoField.YEAR)
.parseCaseInsensitive()
.toFormatter(Locale.ITALIAN);
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);
通过ZoneId,你还可以将LocalDateTime转换为Instant:
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
Instant instantFromDateTime = dateTime.toInstant(romeZone);
你也可以通过反向的方式得到LocalDateTime对象:
Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
“纽约落后于伦敦5小时”。
ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");
略。。。
老
版的java.util.Date
类以及其他用于建模日期时间的类有很多不一致及设计
上的缺陷
,包括易变性以及糟糕的偏移值、默认值和命名。新版
的日期和时间API
中,日期-时间对象是不可变
的。两种
不同的时间表示方式
,有效地区分
了运行时人
和机器
的不同需求。绝对
或者相对
的方式操纵
日期和时间,操作的结果总是返回一个新的实例
,老的日期时间
对象不会发生变化
。TemporalAdjuster
让你能够用更精细
的方式操纵
日期,不再局限于一次只能改变它的一个值,并且你还可按照需求定义自己的日期转换器。笑虾 :Java 学习笔记 - Java8的日期时间 LocalDateTime
笑虾 :Java 学习笔记 - 时间日期常用案列