Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Java.Time.Year arbitrarily limited to less than its primitive limits?

Tags:

java

time

limit

The Java 8 doc page for Java.Time.Year states that the minimum and maximum supported years are -999,999,999 and 999,999,999, respectively.

Field Summary

static int MAX_VALUEThe maximum supported year, '+999,999,999'.

static int MIN_VALUEThe minimum supported year, '-999,999,999'.


However, the primitive type variable that stores the year value is an int, which should be capable of storing between -2,147,483,648 and 2,147,483,647.

/**
 * The year being represented.
 */
private final int year;

Why are there these arbitrary limits?

like image 438
Anthony Mansour Avatar asked Dec 11 '18 20:12

Anthony Mansour


People also ask

What is the maximum and minimum supported year in Java?

The java.time.Year class represents a year in the ISO-8601 calendar system, such as 2007. static int MAX_VALUE − The maximum supported year, '+999,999,999'. static int MIN_VALUE − The minimum supported year, '-999,999,999'.

Why is Java so bad at math?

Java has been criticized for not supporting user-defined operators. Operator overloading improves readability, so its absence can make Java code less readable, especially for classes representing mathematical objects, such as complex numbers and matrices. Java has only one non-numerical use of an operator: + for string concatenation.

What are the disadvantages of Java?

The Java programming language and Java software platform have been criticized for design choices including the implementation of generics, forced object-oriented programming, the handling of unsigned numbers, the implementation of floating-point arithmetic, and a history of security vulnerabilities in the primary Java VM implementation, HotSpot.

What is the use of Java year class?

Java Year class is an immutable date-time object that represents a year. It inherits the Object class and implements the Comparable interface. Let's see the declaration of java.time.Year class. It is used to combine this year with a day-of-year to create a LocalDate. It is used to format this year using the specified formatter.


1 Answers

The reason 999,999,999 is used is not linked to any specific issue with parsing implementation within the code.

It is likely to have been selected as it is the maximum value of any number that consists of between 1 and 9 digits. We cannot store a full set of years to 10 digits with an INT, as 9,999,999,999 (and frankly another 79% of possible 10 digit numbers) cannot be stored in an integer. It is important to note that the formatter itself can support individual numbers up to 64 digits seamlessly, and only uses MIN/MAX for error checking. If the Min/Max were raised to INT_MIN and INT_MAX, it would still function without issues. Values exceeding INT_MAX would properly throw an error and prevent any issues regarding integer overflow, so there is no concern regarding any sort of parse failure.

    ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);

Year is either 4 numbers for traditional ISO, i.e. 0-9999, or has a +/-, i.e. +999999 for Year 999999.

Of note is that the ISO_LOCAL_DATE Formatter accepts 10-digit years by default, excluding the +/- sign, so a value of +9,876,543,210 is actually properly parsed, but exceeds the acceptable values for MAX_YEAR.

Text '+9876543210-10-31' could not be parsed: Invalid value for Year (valid values -999999999 - 999999999): 9876543210

Everything in the DateTimeFormatterBuilder supports up to 64 digits, parsing a digit at a time. All these values are parsed safely as BigIntegers, and carefully multiplied by 10 as the index moves towards the right, and upon completion are converted and stored in a parse context consisting of field names and longs, even though fields Months and Days can clearly be stored as INTS. These are later converted back into their associated primitives.

Practically speaking, DateTimeFormatterBuilder could definitely use 2,147,483,647 as a valid min/max year without breaking.

Realistically speaking, the description of "Java accepts any year value up to 9 digits" presents a concrete barrier where there is no chance of integer overflow or confusion when of adding two years together, and reduces any potential black box confusion as to why year 2,100,000,000 works but 2,200,000,000 breaks to a halt.

like image 170
Compass Avatar answered Oct 26 '22 00:10

Compass