为什么不支持在java.time.Instant中增加几周?

时间:2019-02-24 11:11:49

标签: java time calendar java.time.instant java.time

以下代码:

Instant inFourWeeks = Instant.now().plus(4L, ChronoUnit.WEEKS);

引发异常:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Weeks

为什么不支持数周?我理解为什么不支持数月和数月,因为它们使用较小单位的持续时间可能会有所不同。但是 week 的持续时间(7天)是固定的,我可以这样写:

Instant inFourWeeks = Instant.now().plus(4L * 7L, ChronoUnit.DAYS);

5 个答案:

答案 0 :(得分:5)

每周7天抛出UnsupportedTemporalTypeException并不普遍且持续。不同的日历系统可能会有所不同。例如,查看每周使用6天的Akan日历系统。

答案 1 :(得分:3)

ChronoUnit.WEEKS可以在ISO日历以外的其他日历系统中使用数周。这样的几周可能长达6或10天。因此,尽管可以说Instant支持几天是合理的,但对于几周来说却并非如此。

从文档中:

  

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

     

与其他日历系统一起使用时,必须与   天数的整数。

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

参数的另一部分是Instant不采用一个日历系统,但也可以与其他日历系统一起使用。 (例如,ZonedDateTime相反,假设ISO-8601日历系统也支持星期。)

PS,我想反问一下:为什么Instant支持几天?一天可能是23、23.5、24、24.5或25小时,并且历史上的其他时间也是如此。

链接: Documentation of ChronoUnit.WEEKS

答案 2 :(得分:2)

Instant类处理绝对时间,并尝试避免与不同日历系统,地区和文化 group 解释的方式有关的所有歧义。

某些日历系统具有不同的星期长度,一些具有不同的月分组,具有从不同日期开始的年份,并以不同的方式调整leap年和leap秒(如果有的话,例如朱利安日历的情况)经历了太多的from年,并从本应与之同步的“物理”现象(例如季节,至高无上和春分)中消失了。

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

在Java发生的最后1000秒中,Le秒是“平滑的”,因此从程序员的角度来看,它们不存在。 (计算机时钟仍然不够准确,需要经常与NTP同步。)

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

您必须要注意的一件事是夏令时。在那些特殊的日子里,一天是25个小时还是23个小时,具体取决于时钟的移动方向。但是,Instant类对此并不在意,如果您在夏时制边界上增加1天,它仍将移动24小时。它不包含任何时区或地区信息(DST特定于国家/地区)。

答案 3 :(得分:1)

如果您查看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,周/月/年不能用秒来逻辑一致地表示,因为它们不是通用的竞争内容。

答案 4 :(得分:1)

其他答案正确。我要补充一点说明。

Instant是基本构建块

Instant类是 java.time 类中的基本构建块。它代表一个时刻,是时间轴上的一个点。在内部,它仅是自UTC 1970年第一时刻的纪元参考以来的整数秒数。因此,该类几乎没有功能。

在许多可能的日历系统中的任何一个中,此构造块都可用于跟踪时刻。合理使用Instant并将其视为日期,星期,月份等,取决于特定日历系统的定义。日历系统可以定义一周中的任何天数,或一年中的任何月数,依此类推,或者甚至可能没有这样的概念,例如或一个月。

最明显的日历系统是在整个西方和世界其他地区使用的现代ISO 8601。 OffsetDateTimeZonedDateTime类建立在Instant之上,构成了此ISO日历系统的关键部分。这些类与Instant捆绑在一起只是因为它们被许多Java程序员普遍使用。但是它们绝不是唯一的日历系统。

请查看以下各种日历系统的java.time.chrono软件包:

  • HijrahChronology
    Hijrah calendar是支持伊斯兰日历的阴历。
  • IsoChronology
  • JapaneseChronology
    日本皇室日历系统。
  • MinguoChronology
    Minguo calendar系统。
  • ThaiBuddhistChronology
    泰国佛教历法系统。

ThreeTen-Extra项目为 java.time 类提供了附加功能。这包括更多的日历系统:

  • AccountingChronology
    根据IRS 538号出版物和《国际财务报告准则》,具有52/53周有效的会计日历系统。
  • BritishCutoverChronology
    英国的朱利安-格里高里历转换日历系统。
  • CopticChronology
    Coptic calendar系统。
  • DiscordianChronology
    Discordian calendar系统。
  • InternationalFixedChronology
    International Fixed calendar系统。也称为伊士曼柯达日历。
  • JulianChronology
    多利的儒略历系统,是现代格里高利历和ISO日历的先驱。
  • PaxChronology
    Pax calendar系统。
  • Symmetry010Chronology
  • Symmetry454Chronology
    Symmetry454 calendar系统。

可能我还不知道来自第三方的更多信息。