14

下面的一段代码:

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);
4

5 回答 5

17

它每周抛出UnsupportedTemporalTypeException7 天并不是普遍的和恒定的。它可能因不同的日历系统而异。例如,查看每周使用 6 天的阿寒日历系统。

于 2019-02-24T11:26:55.463 回答
8

Instant课程涉及绝对时间,并试图避免与不同日历系统、地区和文化如何分组解释有关的所有歧义。

一些日历系统有不同的周长,一些有不同的月份分组,年份从不同的日期开始,并以不同的方式调整闰年和闰秒(如果有的话,就像儒略历一样)许多闰年,偏离了它们应该与之同步的“物理”现象,如季节、至日和春分)。

为了避免这些问题,Instant该类允许您使用更精确定义和标准化的单位,如秒、分钟、小时和天。

闰秒在 Java 中被“平滑”了,在它们发生的最后 1000 秒内,所以从程序员的角度来看,它们不存在。(无论如何,计算机时钟并不是那么准确,并且需要经常与 NTP 同步。)

假设 1 天为 24 SI 小时,其中 1 SI 小时定义为 60 SI 分钟,1 SI 分钟定义为 60 SI 秒,1 SI 秒为 Caesium-133 的 9,192,631,770 个辐射周期。24 小时实际上是平均太阳日(两个连续的“中午”之间经过的时间),因为由于椭圆轨道、太阳本身的轨道以及轨道速度的变化,每个太阳日可能会稍长或稍短。

您必须注意的一件重要事情是夏令时。在那些特殊的日子里,一天是 25 小时或 23 小时,这取决于时钟移动的方向。但是,Instant班级并不关心这一点,如果您在夏令时边界上增加 1 天,它仍然会移动 24 小时。它不携带任何时区或地区信息(DST 是特定于国家/地区的)。

于 2019-02-24T11:51:51.043 回答
4

ChronoUnit.WEEKS可以在 ISO 日历以外的其他日历系统中使用数周。并且这样的周可以是例如6天或10天。因此,尽管有人可能认为Instant支持天数是有道理的,但数周内情况并非如此。

从文档中:

代表一周概念的单位。对于 ISO 日历系统,它等于 7 天。

当与其他日历系统一起使用时,它必须对应于整数天。

很明显,WEEKS它通常不采用 ISO 日历系统,也可以与其他日历一起使用。

论点的另一部分是Instant不假设一个日历系统,但也可以与不同的日历系统一起使用。(相比之下,ZonedDateTime例如,假设 ISO-8601 日历系统确实支持周。)

PS我宁愿把问题反过来说:为什么Instant支持天数?一天可能是 23、23.5、24、24.5 或 25 小时,历史上也可能是其他持续时间。

链接: 的文档ChronoUnit.WEEKS

于 2019-02-24T12:22:51.060 回答
3

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.

于 2019-02-25T05:32:52.340 回答
2

如果您查看 的代码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);
     }

从代码中可以清楚地看出,结果是通过将单位的秒表示相乘来计算的,周/月/年不能用秒在逻辑上和一致地表示,因为根据javadoc ,这些不是通用常量。

于 2019-02-24T11:27:47.943 回答