19

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);
Snackoverflow
  • 5,332
  • 7
  • 39
  • 69
  • 1
    Don't assume anything to be of constant duration except those quantities that a `Duration` can represent. "Week" is represented by `Period`. – Sweeper Feb 24 '19 at 11:28
  • 4
    "But a week has constant duration (7 days)" ... not in all calendar systems. – jbx Feb 24 '19 at 11:39
  • Because the [javadoc](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Instant.html#plus(long,java.time.temporal.TemporalUnit)) says so. – Andreas Feb 24 '19 at 11:42
  • 3
    FWIW, `Instant inFourWeeks = (Instant) Period.ofWeeks(4).addTo(Instant.now());` works as a workaround. – Jorn Vernee Feb 24 '19 at 11:42
  • ofWeeks works, but ofYears not.... complicated stuff – lqbweb Aug 11 '22 at 11:16

5 Answers5

20

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.

Amit Bera
  • 7,075
  • 1
  • 19
  • 42
  • @anddero Yes, I believe so. However, I can't give you 100% confirmation on that. The duration of the day should be constant as it defined by rising and setting of the Sun on Earth. – Amit Bera Feb 24 '19 at 11:40
  • @anddero The hour is a standard measure, so the length of a day (24hrs) is standard across all calendar systems (ignoring leap seconds). – jbx Feb 24 '19 at 11:41
  • @AmitBera The duration of a day is defined by the time taken for the earth to do one rotation, not the rising and setting of the Sun. It is on average 24hrs, but sometimes wobbles a bit, which is not taken into consideration in computer time... apart from leap seconds (which are smoothened out over the last 1000 seconds of the day). – jbx Feb 24 '19 at 11:43
  • @jbx You are right. "The duration of a day is defined by the time taken for the earth to do one rotation" is the more accurate definition of a day. – Amit Bera Feb 24 '19 at 11:49
  • More precisely, earth rotation is a *physical* property, not a *cultural* decision. I cannot imagine why some culture might decide that a "day" should be anything else; and in such cases you might simply call the cultural unit differently. For example, "banking day". – Has QUIT--Anony-Mousse Feb 24 '19 at 12:04
  • @Anony-Mousse Yes precisely. But it is also because the `hour` is standardised. – jbx Feb 24 '19 at 12:33
  • I noticed the documentation for `ChronoUnit.MINUTES`: *Unit that represents the concept of a minute. For the ISO calendar system, it is equal to 60 seconds.* So a *minute* might not be standardized? Because it explicitly states "For the **ISO** calendar system" just like it does for `ChronoUnit.WEEKS`. – Snackoverflow Feb 24 '19 at 13:23
  • @anddero Interesting point regarding the definition of minute. UTC standard time actually states: "The number of seconds in a minute is usually 60, but with an occasional leap second, it may be 61 or 59 instead." As I said earlier, Java (and most computer systems) abstract the programmer away from leap seconds and slow down or hurry up negligibly to adjust to it close to where the second needs to be adjusted. – jbx Feb 24 '19 at 14:13
  • Hours, and hence minutes, are much less physically motivated. They are derived from seconds by aggregation, or from days as parts, and because these two definitions don't perfectly agree we have leap seconds... Earth rotation supposedly is not constant, but at least there is a very obvious notion of what 1 rotation is, whereas one second is "the duration of 9,192,631,770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the caesium-133 atom" (at a temperature of 0 K)." – Has QUIT--Anony-Mousse Feb 24 '19 at 17:47
  • One rotation of the Earth can be the time it takes for the sun to be in the same place (24 hours) or until the stars are in the same place (23 hours, 56 minutes). By context, it seems the 24 hour version is desired, and it means it's the sun that matters. – David Zimmerman Feb 26 '19 at 16:52
10

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).

jbx
  • 21,365
  • 18
  • 90
  • 144
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.

Vikas
  • 6,868
  • 4
  • 27
  • 41
4

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 WEEKSdoes 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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Good point regarding the historical day duration. Interestingly, the stellar day is actually 23 hours 56 minutes and 4.1 seconds. – jbx Feb 24 '19 at 12:41
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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154