可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
The following piece of code:
Instant inFourWeeks = Instant.now().plus(4L, ChronoUnit.WEEKS);
Throws an exception:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Weeks
Why are weeks unsupported? I understand why months and years are not supported, because their duration in smaller units may vary. But a week has constant duration (7 days) and I can achieve the same by writing:
Instant inFourWeeks = Instant.now().plus(4L * 7L, ChronoUnit.DAYS);
回答1:
It throws UnsupportedTemporalTypeException
7 days week is not universal and constant. It may vary of different calendar system. For example, look on the Akan calendar system which uses 6 days a week.
回答2:
The Instant
class deals with absolute time, and tries to avoid all ambiguities related to how different calendar systems, regions and cultures group and interpret it.
Some calendar systems have different week lengths, some have different month groupings, have years that start on a different date, and adjust for leap years and leap seconds in different ways (if at all, like in the case of the Julian calendar which had too many leap years and drifted from the 'physical' phenomena they were supposed to be in sync with, like the seasons, solstices and equinox).
To avoid these problems the Instant
class allows you to use the more precisely defined and standardised units like the seconds, minutes, hours and days.
Leap seconds are 'smoothened' out in Java, over the last 1000 seconds of the day on which they occur, so from a programmer's perspective they do not exist. (Computer clocks are not that accurate anyway, and need to sync frequently with NTP.)
1 day is assumed to be 24 SI hours, with 1 SI hour defined as 60 SI minutes, 1 SI minute defined as 60 SI seconds, and 1 SI second being 9,192,631,770 radiation periods of Caesium-133. 24hrs is actually the mean Solar Day (time elapsed between two successive 'noons'), because due to elliptical orbits, the orbit of the sun itself, and variations in orbit speed, each solar day could be slightly longer or shorter.
One important thing you have to be careful of is Daylight Saving. In those special days, a day is 25 hours or 23 hours, depending on which direction the clock moves. However, the Instant
class doesn't care about this, it will still move 24 hours if you add 1 day over the daylight savings boundary. It doesn't carry any timezone or regional information (DST is country specific).
回答3:
ChronoUnit.WEEKS
may be used for weeks in other calendar systems than the ISO calendar. And such weeks may be for example 6 or 10 days long. So while it may be argued that it makes sense that Instant
supports days, the same is not true for weeks.
From the documentation:
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.
It clearly follows from this that WEEKS
does not generally assume the ISO calendar system and may be used with other calendars too.
The other part of the argument is that Instant
does not assume one calendar system but can be used with different calendar systems too. (By contrast, ZonedDateTime
, for example, assumes the ISO-8601 calendar system so does support weeks.)
PS I’d rather put the question the other way around: why does Instant
support days? A day may be 23, 23.5, 24, 24.5 or 25 hours, and historically other durations too.
Link: Documentation of ChronoUnit.WEEKS
.
回答4:
If you look at the code for plus(long, TemporalUnit)
, it does not support 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);
}
From code it is clear that results are calculated by multiplying seconds representation of units, a Week/Month/year can not be logically and consistently represented by seconds as these are not universal contants according to javadoc.
回答5:
Other Answers are correct. I am adding this bit of clarification.
Instant
is basic building-block
The Instant
class is a basic building-block in the java.time classes. It represent a moment, a point on the timeline. Internally it is simply a count of whole seconds since the epoch reference of first moment of 1970 in UTC. So this class is deserving of little functionality.
This building-block may be used to track a moment in any of many possible calendaring systems. Making sense of an Instant
, to treat it as a date, week, month, and so on is up to the definitions of a particular calendaring system. A calendaring system can define any number of days in a week, or any number of months in a year, and so on, or may not even have such concepts as week or month.
The most obvious calendar system is the modern ISO 8601 used throughout the West and other parts of the world. The OffsetDateTime
& ZonedDateTime
classes built on top of Instant
to make up key parts of this ISO calendaring system. These classes are bundled with Instant
merely because they are expected to be commonly used by many Java programmers. But they are by no means the only calendaring system.
Look to the java.time.chrono
package for these various calendar systems:
HijrahChronology
The Hijrah calendar is a lunar calendar supporting Islamic calendars.
IsoChronology
JapaneseChronology
The Japanese Imperial calendar system.
MinguoChronology
The Minguo calendar system.
ThaiBuddhistChronology
The Thai Buddhist calendar system.
The ThreeTen-Extra project provides additional functionality to the java.time classes. This includes more calendaring systems:
AccountingChronology
A proleptic 52/53-week Accounting calendar system per IRS Publication 538 and the International Financial Reporting Standards.
BritishCutoverChronology
The British Julian-Gregorian cutover calendar system.
CopticChronology
The Coptic calendar system.
DiscordianChronology
The Discordian calendar system.
InternationalFixedChronology
The International Fixed calendar system. Also known as the Eastman Kodak calendar.
JulianChronology
The proleptic Julian calendar system, forerunner to the modern Gregorian and ISO calendars.
PaxChronology
The Pax calendar system.
Symmetry010Chronology
Symmetry454Chronology
The Symmetry454 calendar system.
There may be yet more from third-parties that I am not aware of.