首页 > 编程笔记 > Java笔记 阅读:2

Java LocalDate类的用法(附带实例)

在 Java API 中有两种人类时间,本地日期/时间和时区时间。本地日期/时间只有日期与当天的时间,但没有相关的时区信息。

本地日期的一个例子是 1903 年 6 月 14 日(Lambda 演算的发明者阿隆佐·丘奇(Alonzo Church)出生的那天)。由于该日期既没有当天时间,也没有时区信息,因此它并不对应精确的时刻。相比之下,1969 年 7 月 16 日,美国东部时间 09:32:00(阿波罗 11 号发射的时刻)是一个时区日期/时间,表示时间线上的一个精确时刻。

有许多计算并不需要时区,在某些情况下,时区甚至会成为障碍。假设每周 10:00 安排一次会议。如果在最后一个时区时间上加上 7 天(即 7×24×60×60 秒),那么可能会恰好跨越了夏令时的时间调整边界,这次会议将提前一小时或推迟一小时!

因此,API 设计者建议不要使用时区时间,除非确实希望表示绝对时间实例。生日、假日、日程安排时间等建议最好使用本地日期或时间表示。

LocalDate 是包含年、月和日的日期。要构造一个 LocalDate,可以使用 now 或 of 静态方法:
LocalDate today = LocalDate.now(); // Today’s date
LocalDate alonzosBirthday = LocalDate.of(1903, 6, 14);
alonzosBirthday = LocalDate.of(1903, Month.JUNE, 14);
// Uses the Month enumeration
与 Unix 和 java.util.Date 中的不规则约定不同,Unix 和 java.util.Date 中使用的月从 0 开始计算,而年从 1900 开始计算。你需要提供一年中通常使用的月份的数字,也可以使用 Month 枚举。

下表显示了处理 LocalDate 对象的常用方法。

表:LocalDate 方法
方法 功能描述
now, of, ofInstant 这些静态方法从当前时间,从给定的年、月和日,或从 Instant 和 ZoneId 中构造 LocalDate
plusDays, plusWeeks, plusMonths, plusYears 将天数、周数、月数或年数添加到此 LocalDate
minusDays, minusWeeks, minusMonths, minusYears 从该 LocalDate 中减去天数、周数、月数或年数
plus, minus 添加或减去 Duration 或 Period
withDayOfMonth, withDayOfYear, withMonth, withYear 返回一个新的 LocalDate,其中的日期、年份、月份或年份更改为给定值
getDayOfMonth 获取月份日期(1~31)
getDayOfYear 获取年日期(1~366)
getDayOfWeek 获取星期日期,返回 DayOfWeek 枚举值
getMonth, getMonthValue 获取 Month 枚举值表示的月份或者用 1~12 的数字表示的月份
getYear 获取年份,-999999999~999999999
until 获取Period或两个日期之间给定 ChronoUnits 的数量
toEpochSecond 给定 LocalTime 和 ZoneOffset,生成从纪元到指定时间点的秒数
isBefore, isAfter 将此 LocalDate 与另一个 LocalDate 进行比较
isLeapYear 如果年份是闰年,即可以被 4 整除但不能被 100 整除,或可以被 400 整除,则返回 true。该算法适用于过去的所有年份,尽管这在历史上是不准确的。(闰年发明于公元前 46 年,1582 年的公历改革中引入了 100 和 400 整除的规则。这项改革经历了 300 多年才普及。)
dateUntil 给定一个结束日期和一个可选的 Period,将生成从该日期到结束日期的所有日期的 Stream,步长为 1 或给定时段

例如,程序员日是一年中的第 256 天。下面的代码可以轻松计算得到:
LocalDate programmersDay = LocalDate.of(2014, 1, 1).plusDays(255);
// September 13, but in a leap year it would be September 12
回想一下,两个时刻之间的时间差是 Duration。本地日期的等效值是 Period,它表示经过的年数、月数或天数。可以调用 birthday.plus(Period,ofYears(1)) 获得明年的生日。当然,也可以通过调用 birthday.plusYears(1) 来获得。但是 birthday.plus(Duration.ofDays(365)) 不会在闰年产生正确的结果。

until() 方法产生两个本地日期之间的时间差。例如:
independenceDay.until(christmas)
生成一个 5 个月 21 天的时段。这实际上并不是很有用,因为每个月的天数不同。

要查找天数,可以使用:
independenceDay.until(christmas, ChronoUnit.DAYS) // 174 days
上表中的某些方法可能会创建不存在的日期。例如,将 1 月 31 日增加一个月不应该产生 2 月 31 日。这些方法将返回该月的最后一个有效日,而不是抛出异常:
LocalDate.of(2016, 1, 31).plusMonths(1)
LocalDate.of(2016, 3, 31).minusMonths(1)
将得到 2016 年 2 月 29 日。

datesUntil() 方法会生成一个在开始日期和结束日期之间的 LocalDate 流对象:
Stream<LocalDate> allDaysInMay2018 = LocalDate.of(2018,5,1).datesUntil(LocalDate.of(2018,6,1));
Stream<LocalDate> allMondaysIn2018 = LocalDate.of(2018,1,1).datesUntil(LocalDate.of(2019,1,1), Period.ofDays(7));

getDayOfWeek() 生成工作日,是一个 DayOfWeek 枚举值。DayOfWeek.MONDAY 的数值为 1,DayOfWeek.SUNDAY 的数值为 7。例如:
LocalDate.of(1900, 1, 1).getDayOfWeek().getValue()
以上语句将得到 1。DayOfWeek 枚举有方便的 plus() 和 minus() 方法来模 7,从而计算工作日。例如,DayOfWeek.SATURDAY.plus(3) 将获得 DayOfWeek.TUESDAY。

注意,周末实际上是每一周的最后两天。这与 java.util.Calendar 不同。java.util.Calendar 中周日的值为 1,周六的值为 7。

除了 LocalDate,还有 MonthDay、YearMonth 和 Year 类来描述部分日期。例如,12 月 25 日(未指定年份)可以表示为 MonthDay。

相关文章