为什么不支持将周数添加到 java.time.Instant?
Why is adding weeks to java.time.Instant not supported?
下面这段代码:
Instant inFourWeeks = Instant.now().plus(4L, ChronoUnit.WEEKS);
抛出异常:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Weeks
为什么不支持周? 我理解为什么不支持月和年,因为它们在较小单位中的持续时间可能会有所不同。但是 周 有固定的持续时间(7 天),我可以通过写来达到同样的目的:
Instant inFourWeeks = Instant.now().plus(4L * 7L, ChronoUnit.DAYS);
它抛出 UnsupportedTemporalTypeException
每周 7 天不是普遍且不变的。它可能因不同的日历系统而异。例如,查看每周使用 6 天的 Akan 日历系统。
如果您查看 plus(long, TemporalUnit)
的代码,它不支持 WEEK,
@Override
public Instant plus(long amountToAdd, TemporalUnit unit) {
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
case NANOS: return plusNanos(amountToAdd);
case MICROS: return plus(amountToAdd / 1000_000, (amountToAdd % 1000_000) * 1000);
case MILLIS: return plusMillis(amountToAdd);
case SECONDS: return plusSeconds(amountToAdd);
case MINUTES: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_MINUTE));
case HOURS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_HOUR));
case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2));
case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY));
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
return unit.addTo(this, amountToAdd);
}
从代码中可以清楚地看出,结果是通过乘以单位的秒表示来计算的,Week/Month/year 不能在逻辑上和一致地用秒表示,因为根据 javadoc,这些不是通用常量。
Instant
class 处理绝对时间,并尽量避免与不同日历系统、地区和文化 group 和 解释它。
有些日历系统有不同的星期长度,有些有不同的月份分组,年份从不同的日期开始,并以不同的方式调整闰年和闰秒(如果有的话,就像儒略历有太多的闰年,偏离了它们本应与之同步的 'physical' 现象,例如季节、至日和春分)。
为了避免这些问题,Instant
class 允许您使用更精确定义和标准化的单位,例如秒、分钟、小时和天。
闰秒 'smoothened' 在 Java 出现的那一天的最后 1000 秒内,因此从程序员的角度来看它们不存在。 (反正电脑时钟不是那么准确,需要经常和NTP同步。)
假设 1 天为 24 SI 小时,1 SI 小时定义为 60 SI 分钟,1 SI 分钟定义为 60 SI 秒,1 SI 秒为 Caesium-133 的 9,192,631,770 个辐射周期。 24小时实际上是平均太阳日(两个连续'noons'之间经过的时间),因为由于椭圆轨道、太阳本身的轨道和轨道速度的变化,每个太阳日可能会稍微长一些或短一些。
您必须注意的一件重要事情是夏令时。在那些特殊的日子里,一天是 25 小时或 23 小时,这取决于时钟移动的方向。然而,Instant
class 并不关心这个,如果你在夏令时边界上增加 1 天,它仍然会移动 24 小时。它不包含任何时区或区域信息(DST 是特定于国家/地区的)。
ChronoUnit.WEEKS
可以在除 ISO 日历之外的其他日历系统中使用数周。这样的周可能长达 6 天或 10 天。因此,虽然 可能 认为 Instant
支持天数是有道理的,但对于数周来说情况并非如此。
来自文档:
Unit that represents the concept of a week. For the ISO calendar
system, it is equal to 7 days.
When used with other calendar systems it must correspond to an
integral number of days.
由此可见,WEEKS
通常不采用 ISO 日历系统,也可以与其他日历一起使用。
论点的另一部分是 Instant
不假定一个日历系统,但也可以与不同的日历系统一起使用。 (相比之下,例如,ZonedDateTime
假设 ISO-8601 日历系统支持周。)
PS 我宁愿反过来问这个问题:为什么 Instant
支持天数?一天可能是 23、23.5、24、24.5 或 25 小时,历史上也可能是其他持续时间。
其他答案正确。我要补充一点说明。
Instant
是基本积木
Instant
class 是 java.time class 中的基本构建块。它代表一个时刻,时间轴上的一个点。在内部,它只是自 UTC 1970 年第一时刻的纪元参考以来的整秒计数。所以这个 class 不应该有什么功能。
此构建块可用于在许多可能的日历系统中的任何一个中跟踪时刻。理解 Instant
,将其视为日期、周、月等取决于特定日历系统的定义。日历系统可以定义一周中的任意天数,或一年中的任意月数,等等,或者甚至没有这样的概念 或月份。
最明显的日历系统是在西方和世界其他地区使用的现代 ISO 8601。 OffsetDateTime
& ZonedDateTime
classes 建立在 Instant
之上,构成了这个 ISO 日历系统的关键部分。这些 classes 与 Instant
捆绑在一起仅仅是因为它们预计会被许多 Java 程序员普遍使用。但它们绝不是唯一的日历系统。
查看这些不同日历系统的 java.time.chrono
包:
HijrahChronology
Hijrah calendar是支持伊斯兰历的农历。
IsoChronology
JapaneseChronology
日本皇历系统。
MinguoChronology
Minguo calendar系统。
ThaiBuddhistChronology
泰国佛历。
ThreeTen-Extra 项目为 java.time class 提供了额外的功能。这包括更多日历系统:
AccountingChronology
符合美国国税局第 538 号出版物和国际财务报告标准的 52/53 周会计日历系统。
BritishCutoverChronology
英国儒略-格里高利转换日历系统。
CopticChronology
Coptic calendar系统。
DiscordianChronology
Discordian calendar系统。
InternationalFixedChronology
International Fixed calendar系统。也称为伊士曼柯达日历。
JulianChronology
先进的儒略历系统,现代公历和 ISO 日历的先驱。
PaxChronology
Pax calendar系统。
Symmetry010Chronology
Symmetry454Chronology
Symmetry454 calendar系统。
可能还有更多我不知道的第三方。
下面这段代码:
Instant inFourWeeks = Instant.now().plus(4L, ChronoUnit.WEEKS);
抛出异常:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Weeks
为什么不支持周? 我理解为什么不支持月和年,因为它们在较小单位中的持续时间可能会有所不同。但是 周 有固定的持续时间(7 天),我可以通过写来达到同样的目的:
Instant inFourWeeks = Instant.now().plus(4L * 7L, ChronoUnit.DAYS);
它抛出 UnsupportedTemporalTypeException
每周 7 天不是普遍且不变的。它可能因不同的日历系统而异。例如,查看每周使用 6 天的 Akan 日历系统。
如果您查看 plus(long, TemporalUnit)
的代码,它不支持 WEEK,
@Override
public Instant plus(long amountToAdd, TemporalUnit unit) {
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
case NANOS: return plusNanos(amountToAdd);
case MICROS: return plus(amountToAdd / 1000_000, (amountToAdd % 1000_000) * 1000);
case MILLIS: return plusMillis(amountToAdd);
case SECONDS: return plusSeconds(amountToAdd);
case MINUTES: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_MINUTE));
case HOURS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_HOUR));
case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2));
case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY));
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
return unit.addTo(this, amountToAdd);
}
从代码中可以清楚地看出,结果是通过乘以单位的秒表示来计算的,Week/Month/year 不能在逻辑上和一致地用秒表示,因为根据 javadoc,这些不是通用常量。
Instant
class 处理绝对时间,并尽量避免与不同日历系统、地区和文化 group 和 解释它。
有些日历系统有不同的星期长度,有些有不同的月份分组,年份从不同的日期开始,并以不同的方式调整闰年和闰秒(如果有的话,就像儒略历有太多的闰年,偏离了它们本应与之同步的 'physical' 现象,例如季节、至日和春分)。
为了避免这些问题,Instant
class 允许您使用更精确定义和标准化的单位,例如秒、分钟、小时和天。
闰秒 'smoothened' 在 Java 出现的那一天的最后 1000 秒内,因此从程序员的角度来看它们不存在。 (反正电脑时钟不是那么准确,需要经常和NTP同步。)
假设 1 天为 24 SI 小时,1 SI 小时定义为 60 SI 分钟,1 SI 分钟定义为 60 SI 秒,1 SI 秒为 Caesium-133 的 9,192,631,770 个辐射周期。 24小时实际上是平均太阳日(两个连续'noons'之间经过的时间),因为由于椭圆轨道、太阳本身的轨道和轨道速度的变化,每个太阳日可能会稍微长一些或短一些。
您必须注意的一件重要事情是夏令时。在那些特殊的日子里,一天是 25 小时或 23 小时,这取决于时钟移动的方向。然而,Instant
class 并不关心这个,如果你在夏令时边界上增加 1 天,它仍然会移动 24 小时。它不包含任何时区或区域信息(DST 是特定于国家/地区的)。
ChronoUnit.WEEKS
可以在除 ISO 日历之外的其他日历系统中使用数周。这样的周可能长达 6 天或 10 天。因此,虽然 可能 认为 Instant
支持天数是有道理的,但对于数周来说情况并非如此。
来自文档:
Unit that represents the concept of a week. For the ISO calendar system, it is equal to 7 days.
When used with other calendar systems it must correspond to an integral number of days.
由此可见,WEEKS
通常不采用 ISO 日历系统,也可以与其他日历一起使用。
论点的另一部分是 Instant
不假定一个日历系统,但也可以与不同的日历系统一起使用。 (相比之下,例如,ZonedDateTime
假设 ISO-8601 日历系统支持周。)
PS 我宁愿反过来问这个问题:为什么 Instant
支持天数?一天可能是 23、23.5、24、24.5 或 25 小时,历史上也可能是其他持续时间。
其他答案正确。我要补充一点说明。
Instant
是基本积木
Instant
class 是 java.time class 中的基本构建块。它代表一个时刻,时间轴上的一个点。在内部,它只是自 UTC 1970 年第一时刻的纪元参考以来的整秒计数。所以这个 class 不应该有什么功能。
此构建块可用于在许多可能的日历系统中的任何一个中跟踪时刻。理解 Instant
,将其视为日期、周、月等取决于特定日历系统的定义。日历系统可以定义一周中的任意天数,或一年中的任意月数,等等,或者甚至没有这样的概念 或月份。
最明显的日历系统是在西方和世界其他地区使用的现代 ISO 8601。 OffsetDateTime
& ZonedDateTime
classes 建立在 Instant
之上,构成了这个 ISO 日历系统的关键部分。这些 classes 与 Instant
捆绑在一起仅仅是因为它们预计会被许多 Java 程序员普遍使用。但它们绝不是唯一的日历系统。
查看这些不同日历系统的 java.time.chrono
包:
HijrahChronology
Hijrah calendar是支持伊斯兰历的农历。IsoChronology
JapaneseChronology
日本皇历系统。MinguoChronology
Minguo calendar系统。ThaiBuddhistChronology
泰国佛历。
ThreeTen-Extra 项目为 java.time class 提供了额外的功能。这包括更多日历系统:
AccountingChronology
符合美国国税局第 538 号出版物和国际财务报告标准的 52/53 周会计日历系统。BritishCutoverChronology
英国儒略-格里高利转换日历系统。CopticChronology
Coptic calendar系统。DiscordianChronology
Discordian calendar系统。InternationalFixedChronology
International Fixed calendar系统。也称为伊士曼柯达日历。JulianChronology
先进的儒略历系统,现代公历和 ISO 日历的先驱。PaxChronology
Pax calendar系统。Symmetry010Chronology
Symmetry454Chronology
Symmetry454 calendar系统。
可能还有更多我不知道的第三方。