概述
- LocalDate 日期
- LocalTime 时间
- LocalDateTime 日期+时间
- ZonedDateTime 日期+时间+时区
- Instant 时间戳
- OffsetTime
- OffsetDateTime
日期类
LocalDate,YearMonth,MonthDay 和 Year
LocalDate
// 2021-11-20
LocalDate date = LocalDate.of(2021, Month.NOVEMBER, 20);
// 当前指定日期的下一个 星期三
LocalDate nextWed = date.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
// 格式化输出
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(date));
YearMonth
YearMonth.lengthOfMonth(),返回该月有多少天
YearMonth.lengthOfYear(),返回该年有多少天
// 2021-06: 30
YearMonth date = YearMonth.now();
System.out.printf("%s: %d%n", date, date.lengthOfMonth());
// 2021-02: 28
YearMonth date2 = YearMonth.of(2021, Month.FEBRUARY);
System.out.printf("%s: %d%n", date2, date2.lengthOfMonth());
// 2012-02: 366
YearMonth date3 = YearMonth.of(2012, Month.FEBRUARY);
System.out.printf("%s: %d%n", date3, date3.lengthOfYear());
MonthDay
表示某月的一天
// 2月29号
MonthDay date = MonthDay.of(Month.FEBRUARY, 29);
// 对于 2010 年是否是有效的时间
boolean validLeapYear = date.isValidYear(2010);
Year
// 确定给定年份是否为闰年
boolean validLeapYear = Year.of(2012).isLeap();
日期和时间类
LocalTime
LocalTime类不存储时区或夏令时信息
LocalTime thisSec = LocalTime.now();
System.out.println(thisSec.getHour() + ":" + thisSec.getMinute() + ":" + thisSec.getSecond());
LocalDateTime
LocalDate 和 LocalTime 的组合,无时区
// now()
System.out.printf("now: %s%n", LocalDateTime.now());
// of(), 1994年4月15号11点30分
System.out.printf("Apr 15, 1994 @ 11:30am: %s%n",
LocalDateTime.of(1994, Month.APRIL, 15, 11, 30));
// ofInstant(), 基于Instant类,纳秒 + 时区id
System.out.printf("now (from Instant): %s%n",
LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
// plusMonth(), 6月后
System.out.printf("6 months from now: %s%n",
LocalDateTime.now().plusMonths(6));
// minusMonths(), 6月前
System.out.printf("6 months ago: %s%n",
LocalDateTime.now().minusMonths(6));
时区和偏移类
// 在中国,下面获取到的就是带时区的北京时间,里面的 offset 就是 +8:00
ZonedDateTime.now()
ZoneId + ZoneOffset
ZoneId: 指定时区标识符,并提供 Instant 和 LocalDateTime 之间转换的规则
ZoneOffset: 指定格林威治/ UTC 时间的时区偏移量
// 获取所有可用的时区
Set<String> allZones = ZoneId.getAvailableZoneIds();
// 本地时间加时区信息 转换成一个ZonedDateTime
LocalDateTime dt = LocalDateTime.now();
ZoneId zone = ZoneId.of(s);
ZonedDateTime zdt = dt.atZone(zone);
// 针对IUTC时间的时区偏移量
ZoneOffset offset = zdt.getOffset();
ZonedDateTime
使用格林威治/ UTC 的时区偏移量处理具有相应时区的日期和时间
结合了 LocalDateTime 与类 了 zoneid 类
表示具有时区的完整日期和时间
// DateTimeFormatter 对象用于格式化 ZonedDateTime 实例
DateTimeFormatter format = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
// 时间 + 日期 LocalDateTime + 时区 ZoneId => 时间 + 日期 + 时区 ZonedDateTime
// 2013-07-20 19:30:00
LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneId leavingZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);
// 格式化
String out1 = departure.format(format);
// 切换时区(使用美国洛杉矶出发的时间,然后换算成东京的时区,返回该时区对应的时间)
ZoneId arrivingZone = ZoneId.of("Asia/Tokyo");
ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone);
// 在该时区的基础上加650分钟
arrival = arrival.plusMinutes(650);
// 格式化
String out2 = arrival.format(format);
// 夏令时
arrivingZone.getRules().isDaylightSavings(arrival.toInstant());
OffsetDateTime
使用格林威治/ UTC 的相应时区偏移量处理日期和时间,但不包含时区 ID
结合了 LocalDateTime 与类 ZoneOffset 类
// 2017.07.20 19:30
LocalDateTime localDate = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneOffset offset = ZoneOffset.of("-08:00");
OffsetDateTime offsetDate = OffsetDateTime.of(localDate, offset);
OffsetTime
使用格林威治/ UTC 的相应时区偏移量处理时间,但不包含时区 ID
ZonedDateTime和OffsetDateTime
// 一个不带任何时区的时间
LocalDateTime date = LocalDateTime.of(2018, 05, 01, 0, 0, 0);
// ZonedDateTime, 2018-05-01T00:00+08:00[GMT+08:00], ZoneId 带了具体的ID
ZonedDateTime d1 = ZonedDateTime.of(date, ZoneId.systemDefault());
// OffsetDateTime, 2018-05-01T00:00+08:00, 偏移没有ID,因为多个ID对应的值有可能是一样的
ZoneOffset offset = ZoneOffset.of("+08:00");
OffsetDateTime d2 = OffsetDateTime.of(date, offset);
常用api
// 么把中国时间变成其他的时间
// 2018-04-30T20:00+04:00[Asia/Yerevan]
// 把该时间转换成指定时区了
d1.withZoneSameInstant(ZoneId.of("Asia/Yerevan"));
// 2018-05-01T00:00+04:00[Asia/Yerevan]
// 只是改变了时区
d1.withZoneSameLocal(ZoneId.of("Asia/Yerevan"));
withZoneSameInstant
调用了 toEpochSecond 把当前的时间纳秒 结合 指定的偏移量换算成新的纳秒
withZoneSameLocal
不会换算时间,只是把时区更改了
Instant
Instant timestamp = Instant.now();
// 增加1h
Instant oneHourLater = Instant.now().plusHours(1);
// until,返回两者直接发生了多长的时间
long secondsFromEpoch = Instant.ofEpochSecond(0L).until(Instant.now(),
ChronoUnit.SECONDS);
解析和格式化
DateTimeFormatter 类提供了大量预定义的格式化,也可以自己定义
DateTimeFormatter 类是不可变的和线程安全的
parse
// 预定义
String in = "20111203";
LocalDate date = LocalDate.parse(in, DateTimeFormatter.BASIC_ISO_DATE);
// 自定义
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy");
LocalDate date = LocalDate.parse(input, formatter);
format
ZoneId leavingZone = ZoneId.systemDefault();
ZonedDateTime departure = ZonedDateTime.of(LocalDateTime.now(), leavingZone);
DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");
String out = departure.format(format);
dtf.parse("2018-05-08 16:03:55") 返回的对象中 不包含 LocalDate 只包含 LocalTime
// 以下两种方式相等
LocalDateTime.parse("2018-05-08 16:03:55",dtf);
dtf.parse("2018-05-08 16:03:55").query(LocalDateTime::from);
PS: 参考文档,zq99299.github.io/java-tutori…