在 Java8 API 中,有两种人类时间,本地日期/时间和带时区的时间。本地日期/时间表示一个日期和/或一天中是时间,但是不关联任何时区信息。例如,June 14,1903 就是一个本地日期。由于日期既不含一天中的时间,也不含时区信息,所以它无法与一个准确的瞬时点对应。相反,July 16,1969,09:32:00 EDT 就是一个带时区的日期/时间,它表示了时间轴上准确的一点。
有许多计算是不需要时区的,并且在某些情况下,考虑时区甚至可能导致错误的结果。假设你安排了一个每周 10:00 的会议,如果你在上一次带时区的时间上添加了 7 天,并且这期间恰好越过了夏令时,那么会议就会被提前或推迟1小时!
什么是夏令时?
夏令时(Daylight Saving Time,简称DST),又称“夏时制”、“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度。在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季,人们会人为将时间调快一小时,这样可以使人早起早睡,减少照明用电,以充分利用光照资源。
出于以上原因,API 的设计者们推荐不使用带时区的时间,除非你真的希望表示绝对的瞬时点。生日、假期、会议时间等,最好都用本地日期或时间来表示。
LocalDate 是一个不可变的日期时间对象,表示日期,通常被视为年月日。也可以访问其他日期字段,例如日期,星期几和星期。 例如,值“2007年10月2日”可存储在 LocalDate 。
LocalDate 不存储或表示时间或时区。相反,它是日期的描述,用于生日、纪念日等。它不能代表时间线上的瞬时信息( Instant),且没有附加信息,如偏移或时区。
LocalDate 主要特点:
不可变性:LocalDate 实例是不可变的,一旦创建就不能更改。
线程安全:由于不可变性,LocalDate 实例是线程安全的。
无时区:LocalDate 仅表示日期,没有时区信息。
工厂方法:提供了多种静态方法来创建 LocalDate 实例,如 now(), of(), parse() 等。
调整日期:提供了 plusDays(), plusWeeks(), plusMonths(), plusYears() 等方法来调整日期。
查询日期:提供了 getDayOfMonth(), getDayOfWeek(), getMonth(), getYear() 等方法来查询日期的各个部分。
日期比较:可以使用 equals(), isBefore(), isAfter() 等方法来比较两个日期。
日期格式化:可以使用 DateTimeFormatter 类来格式化 LocalDate 实例。
要创建一个 LocalDate,你可以使用静态方法 now() 或者 of(),例如:
package com.hxstrive.jdk8.date_time.local_date; import java.time.LocalDate; /** * LocalDate 类 * @author hxstrive.com */ public class LocalDateDemo1 { public static void main(String[] args) { // 使用当前日期创建LocalDate实例 LocalDate today = LocalDate.now(); System.out.println("Today's date: " + today); // 使用指定的年月日创建LocalDate实例 LocalDate someDate = LocalDate.of(2023, 3, 15); System.out.println("Specific date: " + someDate); // 解析字符串创建LocalDate实例 LocalDate parsedDate = LocalDate.parse("2023-03-15"); System.out.println("Parsed date: " + parsedDate); //输出: //Today's date: 2024-06-29 //Specific date: 2023-03-15 //Parsed date: 2023-03-15 } }
LocalDate 类提供了一些方法来调整日期,如:plusDays(), plusWeeks(), plusMonths(), plusYears() 等方法。例如:
package com.hxstrive.jdk8.date_time.local_date; import java.time.LocalDate; /** * LocalDate 类 * @author hxstrive.com */ public class LocalDateDemo2 { public static void main(String[] args) { // 使用当前日期创建 LocalDate 实例 LocalDate today = LocalDate.now(); System.out.println("Today's date: " + today); // Today's date: 2024-06-29 // 使用 plusYears 方法增加 10 年 LocalDate localDate1 = today.plusYears(10); System.out.println(localDate1); // 2034-06-29 // 使用 plusMonths 方法增加 5 个月 LocalDate localDate2 = today.plusMonths(5); System.out.println(localDate2); // 2024-11-29 // 使用 plusWeeks 方法增加 2 周 LocalDate localDate3 = today.plusWeeks(2); System.out.println(localDate3); // 2024-07-13 // 使用 plusDays 方法增加 30 天 LocalDate localDate4 = today.plusDays(30); System.out.println(localDate4); // 2024-07-29 } }
LocalDate 类提供了多种方法来查询日期的相关信息,以下是一些常见的方法:
getYear():获取年份。
getMonthValue():获取月份,返回 1 到 12 的整数值。
getMonth():获取月份,返回Month枚举类型。
getDayOfMonth():获取该月的第几天。
getDayOfYear():获取该年的第几天。
getDayOfWeek():获取星期几,返回 DayOfWeek 枚举类型。DayOfWeek 是一个枚举类型,用于表示一周中的星期几,取值如下:
MONDAY 表示星期一
TUESDAY 表示星期二
WEDNESDAY 表示星期三
THURSDAY 表示星期四
FRIDAY 表示星期五
SATURDAY 表示星期六
SUNDAY 表示星期天
DayOfWeek 枚举还提供了一些方便的方法 plus 和 minus, 用来计算值为 7 是星期几。例如 Dayofweek.SATURDAY.plus(3) 会返回 DayofWeek.TUESDAY。
注意:DayOfWeek 中周末实际上位于一周的末尾,这与 java.util.Calendar 不同。在 java.util.Calendar 中,周日的值为1, 而周六的值为7。
示例:
package com.hxstrive.jdk8.date_time.local_date; import java.time.LocalDate; /** * LocalDate 类 * @author hxstrive.com */ public class LocalDateDemo3 { public static void main(String[] args) { LocalDate today = LocalDate.now(); int year = today.getYear(); System.out.println("年份: " + year); //年份: 2024 int monthValue = today.getMonthValue(); System.out.println("月份(数字): " + monthValue); //月份(数字): 6 java.time.Month month = today.getMonth(); System.out.println("月份(枚举): " + month); //月份(枚举): JUNE int dayOfMonth = today.getDayOfMonth(); System.out.println("该月第几天: " + dayOfMonth); //该月第几天: 29 int dayOfYear = today.getDayOfYear(); System.out.println("该年第几天: " + dayOfYear); //该年第几天: 181 java.time.DayOfWeek dayOfWeek = today.getDayOfWeek(); System.out.println("星期几(枚举): " + dayOfWeek); //星期几(枚举): SATURDAY boolean leapYear = today.isLeapYear(); System.out.println("是否是闰年: " + leapYear); //是否是闰年: true } }
LocalDate 类提供了一些用于日期比较的方法,常见的有:
isBefore(other):判断当前日期是否在另一个日期之前,如果是则返回true,否则返回false。
isAfter(other):判断当前日期是否在另一个日期之后,如果是则返回true,否则返回false。
isEqual(other):判断当前日期与另一个日期是否相等,如果相等则返回true,否则返回false。
例如:
package com.hxstrive.jdk8.date_time.local_date; import java.time.LocalDate; /** * LocalDate 类 * @author hxstrive.com */ public class LocalDateDemo4 { public static void main(String[] args) { LocalDate date1 = LocalDate.of(2024, 6, 29); LocalDate date2 = LocalDate.of(2024, 7, 1); // 判断 date1 是否在 date2 之前 boolean isBefore = date1.isBefore(date2); System.out.println("date1 在 date2 之前? " + isBefore); //date1 在 date2 之前? true // 判断 date1 是否在 date2 之后 boolean isAfter = date1.isAfter(date2); System.out.println("date1 在 date2 之后? " + isAfter); //date1 在 date2 之后? false // 判断 date1 是否与 date2 相等 boolean isEqual = date1.isEqual(date2); System.out.println("date1 与 date2 相等? " + isEqual); //date1 与 date2 相等? false } }