方法命名约定
原文:
docs.oracle.com/javase/tutorial/datetime/overview/naming.html
日期时间 API 提供了丰富的方法集合,涵盖了丰富的类。在可能的情况下,方法名称在类之间保持一致。例如,许多类提供了一个now
方法,用于捕获与该类相关的当前时刻的日期或时间值。还有from
方法允许从一个类转换为另一个类。
方法名称前缀也有标准化。由于日期时间 API 中的大多数类都是不可变的,API 不包括set
方法。(创建后,不可变对象的值不能更改。set
方法的不可变等效方法是with
。)以下表列出了常用的前缀:
前缀 | 方法类型 | 用途 |
of |
静态工厂 | 创建一个实例,其中工厂主要验证输入参数,而不是转换它们。 |
from |
静态工厂 | 将输入参数转换为目标类的实例,这可能涉及从输入中丢失信息。 |
parse |
静态工厂 | 解析输入字符串以生成目标类的实例。 |
format |
实例 | 使用指定的格式化程序格式化时间对象中的值以生成字符串。 |
get |
实例 | 返回目标对象的状态的一部分。 |
is |
实例 | 查询目标对象的状态。 |
with |
实例 | 返回目标对象的副本,其中一个元素已更改;这相当于 JavaBean 上的set 方法的不可变版本。 |
plus |
实例 | 返回目标对象的副本,其中添加了一定数量的时间。 |
minus |
实例 | 返回目标对象的副本,其中减去了一定数量的时间。 |
to |
实例 | 将此对象转换为另一种类型。 |
at |
实例 | 将此对象与另一个对象组合。 |
课程:标准日历
日期时间 API 的核心是java.time包。java.time
中定义的类基于 ISO 日历系统,这是代表日期和时间的世界标准。ISO 日历遵循普罗列普提克格里高利规则。格里高利日历于 1582 年引入;在普罗列普提克格里高利日历中,日期从那时开始向前延伸,以创建一致的、统一的时间线,并简化日期计算。
本课程涵盖以下主题:
概述
这一部分比较了人类时间和机器时间的概念,并提供了java.time
包中主要基于时间的类的表格。
星期几和月份枚举
这一部分讨论了定义星期几(DayOfWeek
)和定义月份(Month
)的枚举。
日期类
这一部分展示了仅处理日期而不涉及时间或时区的基于时间的类。这四个类分别是LocalDate
、YearMonth
、MonthDay
和Year
。
日期和时间类
这一部分介绍了处理时间和日期时间的LocalTime
和LocalDateTime
类,但不涉及时区。
时区和偏移类
这一部分讨论了存储时区(或时区偏移)信息的基于时间的类,ZonedDateTime
、OffsetDateTime
和OffsetTime
。还讨论了支持类ZoneId
、ZoneRules
和ZoneOffset
。
Instant 类
这一部分讨论了Instant
类,它表示时间轴上的瞬时时刻。
解析和格式化
这一部分概述了如何使用预定义的格式化程序来格式化和解析日期和时间值。
时间包
这一部分概述了java.time.temporal
包,支持时间类、字段(TemporalField
和ChronoField
)和单位(TemporalUnit
和ChronoUnit
)。这一部分还解释了如何使用时间调整器来检索调整后的时间值,比如“4 月 11 日后的第一个星期二”,以及如何执行时间查询。
周期和持续时间
这一部分解释了如何计算一段时间,使用了Period
和Duration
类,以及ChronoUnit.between
方法。
时钟
这一部分简要介绍了Clock
类。您可以使用这个类来提供一个替代时钟来替代系统时钟。
非 ISO 日期转换
这一部分解释了如何将 ISO 日历系统中的日期转换为非 ISO 日历系统中的日期,比如JapaneseDate
或ThaiBuddhistDate
。
遗留日期时间代码
本节提供了一些关于如何将旧的java.util.Date
和java.util.Calendar
代码转换为日期时间 API 的技巧。
摘要
本节提供了标准日历课程的摘要。
概述
原文:
docs.oracle.com/javase/tutorial/datetime/iso/overview.html
有两种基本表示时间的方式。一种方式以人类术语表示时间,称为人类时间,例如年、月、日、小时、分钟和秒。另一种方式,机器时间,连续测量时间沿着时间线从一个起点,称为纪元,以纳秒分辨率。日期时间包提供了丰富的类来表示日期和时间。日期时间 API 中的一些类旨在表示机器时间,而另一些更适合表示人类时间。
首先确定您需要日期和时间的哪些方面,然后选择满足这些需求的类或类。在选择基于时间的类时,首先确定您需要表示人类时间还是机器时间。然后确定您需要表示时间的哪些方面。您需要时区吗?日期和时间?仅日期?如果您需要日期,您需要月、日、和年,还是一个子集?
术语: 在日期时间 API 中捕获和处理日期或时间值的类,如Instant
、LocalDateTime
和ZonedDateTime
,在本教程中统称为基于时间的类(或类型)。不包括支持类型,如TemporalAdjuster
接口或DayOfWeek
枚举。
例如,您可能会使用LocalDate
对象来表示出生日期,因为大多数人都在同一天庆祝生日,无论他们是在出生城市还是在国际日期变更线的另一边的地球上。如果您正在跟踪占星时间,那么您可能希望使用LocalDateTime
对象来表示出生日期和时间,或者ZonedDateTime
,它还包括时区。如果您正在创建时间戳,那么您很可能会使用Instant
,它允许您比较时间线上的一个瞬时点和另一个。
以下表格总结了java.time
包中存储日期和/或时间信息的基于时间的类,或者可用于测量时间量的类。列中的勾号表示该类使用该特定类型的数据,toString 输出列显示使用toString
方法打印的实例。讨论位置列链接到教程中相关页面。
类或枚举 | 年 | 月 | 日 | 小时 | 分钟 | 秒* | 时区偏移 | 时区 ID | toString 输出 | 讨论位置 |
Instant |
2013-08-20T15:16:26.355Z |
Instant 类 | ||||||||
LocalDate |
2013-08-20 |
日期类 | ||||||||
LocalDateTime |
2013-08-20T08:16:26.937 |
日期和时间类 | ||||||||
ZonedDateTime |
2013-08-21T00:16:26.941+09:00[亚洲/东京] |
时区和偏移类 | ||||||||
LocalTime |
08:16:26.943 |
日期和时间类 | ||||||||
MonthDay |
--08-20 |
日期类 | ||||||||
Year |
2013 |
日期类 | ||||||||
YearMonth |
2013-08 |
日期类 | ||||||||
Month |
八月 |
星期几和月份枚举 | ||||||||
OffsetDateTime |
2013-08-20T08:16:26.954-07:00 |
时区和偏移类 | ||||||||
OffsetTime |
08:16:26.957-07:00 |
时区和偏移类 | ||||||||
Duration |
** | ** | ** | PT20H (20 小时) |
周期和持续时间 | |||||
Period |
*** | *** | P10D (10 天) |
周期和持续时间 | ||||||
* | 秒被捕捉到纳秒精度。 | |||||||||
** | 这个类不存储这些信息,但有方法提供这些单位的时间。 | |||||||||
*** | 当Period 添加到ZonedDateTime 时,会考虑夏令时或其他本地时间差异。 |
DayOfWeek 和 Month 枚举
日期时间 API 提供了用于指定星期几和每年月份的枚举。
DayOfWeek
DayOfWeek
枚举由描述一周中每天的七个常量组成:MONDAY
到SUNDAY
。DayOfWeek
常量的整数值范围从 1(星期一)到 7(星期日)。使用定义的常量(DayOfWeek.FRIDAY
)可以使您的代码更易读。
这个枚举还提供了许多方法,类似于时间为基础的类提供的方法。例如,以下代码将“Monday”加 3 天并打印结果。输出为“THURSDAY”:
System.out.printf("%s%n", DayOfWeek.MONDAY.plus(3));
使用getDisplayName(TextStyle, Locale)
方法,您可以检索一个字符串来标识用户所在地区的星期几。TextStyle
枚举允许您指定要显示的字符串类型:FULL
、NARROW
(通常是一个字母)或SHORT
(缩写)。STANDALONE
的TextStyle
常量在某些语言中使用,当作为日期的一部分时输出不同于单独使用时的输出。以下示例打印了“Monday”三种主要形式的TextStyle
:
DayOfWeek dow = DayOfWeek.MONDAY; Locale locale = Locale.getDefault(); System.out.println(dow.getDisplayName(TextStyle.FULL, locale)); System.out.println(dow.getDisplayName(TextStyle.NARROW, locale)); System.out.println(dow.getDisplayName(TextStyle.SHORT, locale));
此代码在en
区域设置下的输出如下:
Monday M Mon
月
Month
枚举包括了十二个月的常量,从JANUARY
到DECEMBER
。与DayOfWeek
枚举一样,Month
枚举是强类型的,每个常量的整数值对应 ISO 范围从 1(一月)到 12(十二月)。使用定义的常量(Month.SEPTEMBER
)可以使您的代码更易读。
Month
枚举还包括许多方法。以下代码使用maxLength
方法打印二月份最大可能的天数。输出为“29”:
System.out.printf("%d%n", Month.FEBRUARY.maxLength());
Month
枚举还实现了getDisplayName(TextStyle, Locale)
方法,使用指定的TextStyle
检索一个字符串来标识用户所在地区的月份。如果特定的TextStyle
未定义,则返回表示常量数值的字符串。以下代码使用三种主要文本样式打印八月份的月份:
Month month = Month.AUGUST; Locale locale = Locale.getDefault(); System.out.println(month.getDisplayName(TextStyle.FULL, locale)); System.out.println(month.getDisplayName(TextStyle.NARROW, locale)); System.out.println(month.getDisplayName(TextStyle.SHORT, locale));
此代码在en
区域设置下的输出如下:
August A Aug
日期类
日期时间 API 提供了四个专门处理日期信息的类,不考虑时间或时区。这些类的使用建议由类名决定:LocalDate
、YearMonth
、MonthDay
和Year
。
LocalDate
LocalDate
表示 ISO 日历中的年-月-日,用于表示没有时间的日期。您可以使用LocalDate
来跟踪重要事件,如出生日期或结婚日期。以下示例使用of
和with
方法创建LocalDate
实例:
LocalDate date = LocalDate.of(2000, Month.NOVEMBER, 20); LocalDate nextWed = date.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
有关TemporalAdjuster
接口的更多信息,请参见时间调整器。
除了通常的方法外,LocalDate
类还提供了用于获取有关给定日期信息的 getter 方法。getDayOfWeek
方法返回特定日期所在的星期几。例如,以下代码返回"MONDAY":
DayOfWeek dotw = LocalDate.of(2012, Month.JULY, 9).getDayOfWeek();
以下示例使用TemporalAdjuster
来获取特定日期后的第一个星期三。
LocalDate date = LocalDate.of(2000, Month.NOVEMBER, 20); TemporalAdjuster adj = TemporalAdjusters.next(DayOfWeek.WEDNESDAY); LocalDate nextWed = date.with(adj); System.out.printf("For the date of %s, the next Wednesday is %s.%n", date, nextWed);
运行代码会产生以下结果:
For the date of 2000-11-20, the next Wednesday is 2000-11-22.
Period and Duration 部分还有使用LocalDate
类的示例。
YearMonth
YearMonth
类表示特定年份的月份。以下示例使用YearMonth.lengthOfMonth()
方法来确定几个年份和月份组合的天数。
YearMonth date = YearMonth.now(); System.out.printf("%s: %d%n", date, date.lengthOfMonth()); YearMonth date2 = YearMonth.of(2010, Month.FEBRUARY); System.out.printf("%s: %d%n", date2, date2.lengthOfMonth()); YearMonth date3 = YearMonth.of(2012, Month.FEBRUARY); System.out.printf("%s: %d%n", date3, date3.lengthOfMonth());
此代码的输出如下:
2013-06: 30 2010-02: 28 2012-02: 29
MonthDay
MonthDay
类表示特定月份的某一天,例如 1 月 1 日的元旦。
以下示例使用MonthDay.isValidYear
方法来确定 2010 年 2 月 29 日是否有效。调用返回false
,确认 2010 年不是闰年。
MonthDay date = MonthDay.of(Month.FEBRUARY, 29); boolean validLeapYear = date.isValidYear(2010);
Year
Year
类表示一年。以下示例使用Year.isLeap
方法来确定给定年份是否是闰年。调用返回true
,确认 2012 年是闰年。
boolean validLeapYear = Year.of(2012).isLeap();
日期和时间类
原文:
docs.oracle.com/javase/tutorial/datetime/iso/datetime.html
LocalTime
LocalTime
类类似于其他以Local
为前缀的类,但仅处理时间。这个类非常适用于表示人类时间,比如电影时间,或者当地图书馆的开放和关闭时间。它也可以用来创建数字时钟,就像下面的例子所示:
LocalTime thisSec; for (;;) { thisSec = LocalTime.now(); // implementation of display code is left to the reader display(thisSec.getHour(), thisSec.getMinute(), thisSec.getSecond()); }
LocalTime
类不存储时区或夏令时信息。
LocalDateTime
处理日期和时间,不带时区的类是LocalDateTime
,是日期时间 API 的核心类之一。这个类用于表示日期(月-日-年)和时间(时-分-秒-纳秒),实际上是LocalDate
和LocalTime
的组合。这个类可以用来表示特定事件,比如 2013 年 8 月 17 日下午 1:10 开始的美洲杯挑战者系列赛首场路易威登杯决赛。请注意,这意味着当地时间下午 1:10。要包含时区,必须使用ZonedDateTime
或OffsetDateTime
,如时区和偏移类中所讨论的。
除了每个基于时间的类都提供的now
方法外,LocalDateTime
类还有各种of
方法(或以of
为前缀的方法)来创建LocalDateTime
的实例。还有一个from
方法,用于将另一种时间格式的实例转换为LocalDateTime
实例。还有用于添加或减去小时、分钟、天、周和月份的方法。下面的例子展示了其中一些方法。日期时间表达式用粗体表示:
System.out.printf("now: %s%n", LocalDateTime.now()); System.out.printf("Apr 15, 1994 @ 11:30am: %s%n", LocalDateTime.of(1994, Month.APRIL, 15, 11, 30)); System.out.printf("now (from Instant): %s%n", LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); System.out.printf("6 months from now: %s%n", LocalDateTime.now().plusMonths(6)); System.out.printf("6 months ago: %s%n", LocalDateTime.now().minusMonths(6));
这段代码产生的输出看起来类似于以下内容:
now: 2013-07-24T17:13:59.985 Apr 15, 1994 @ 11:30am: 1994-04-15T11:30 now (from Instant): 2013-07-24T17:14:00.479 6 months from now: 2014-01-24T17:14:00.480 6 months ago: 2013-01-24T17:14:00.481
时区和偏移类
时区是地球上使用相同标准时间的区域。每个时区由一个标识符描述,通常具有region/city(Asia/Tokyo
)的格式和与格林威治/协调世界时的偏移。例如,东京的偏移是+09:00
。
ZoneId 和 ZoneOffset
日期时间 API 提供了两个用于指定时区或偏移的类:
ZoneId
指定了一个时区标识符,并提供了在Instant
和LocalDateTime
之间转换的规则。ZoneOffset
指定了与格林威治/协调世界时的时区偏移。
从格林威治/协调世界时的偏移通常以整小时定义,但也有例外情况。以下代码来自TimeZoneId
示例,打印了所有使用非整小时定义的格林威治/协调世界时偏移的时区列表。
Set<String> allZones = ZoneId.getAvailableZoneIds(); LocalDateTime dt = LocalDateTime.now(); // Create a List using the set of zones and sort it. List<String> zoneList = new ArrayList<String>(allZones); Collections.sort(zoneList); ... for (String s : zoneList) { ZoneId zone = ZoneId.of(s); ZonedDateTime zdt = dt.atZone(zone); ZoneOffset offset = zdt.getOffset(); int secondsOfHour = offset.getTotalSeconds() % (60 * 60); String out = String.format("%35s %10s%n", zone, offset); // Write only time zones that do not have a whole hour offset // to standard out. if (secondsOfHour != 0) { System.out.printf(out); } ... }
此示例将以下列表打印到标准输出:
America/Caracas -04:30 America/St_Johns -02:30 Asia/Calcutta +05:30 Asia/Colombo +05:30 Asia/Kabul +04:30 Asia/Kathmandu +05:45 Asia/Katmandu +05:45 Asia/Kolkata +05:30 Asia/Rangoon +06:30 Asia/Tehran +04:30 Australia/Adelaide +09:30 Australia/Broken_Hill +09:30 Australia/Darwin +09:30 Australia/Eucla +08:45 Australia/LHI +10:30 Australia/Lord_Howe +10:30 Australia/North +09:30 Australia/South +09:30 Australia/Yancowinna +09:30 Canada/Newfoundland -02:30 Indian/Cocos +06:30 Iran +04:30 NZ-CHAT +12:45 Pacific/Chatham +12:45 Pacific/Marquesas -09:30 Pacific/Norfolk +11:30
TimeZoneId
示例还会将所有时区 ID 打印到名为timeZones
的文件中。
Java 中文官方教程 2022 版(二十八)(2)/article/1486867