Search code examples
javadategregorian-calendarjulian-date

Why does GregorianCalendar.getInstance contain a calsys and cdate of type Julian Calendar


I tried to do set date value to a PreparedStatement with default value but the value is sometimes returned as a JulianValue. For example (Assume spanBegin and spanEnd are null)

Calendar cal = new GregorianCalendar();
if (spanBegin == null) {
    cal.set(0000, Calendar.JANUARY, 1);
    spanBegin = cal.getTime();
}

if (spanEnd == null)
{
    cal.set(9999, Calendar.DECEMBER, 31);
    spanEnd = cal.getTime();
}

On line number 3, since the date January 1, 0000 is scoped by a Julian Calendar, the CDate becomes a Julian Calendar. However, the next Date even if it is in the year 9999, its CDate becomes a Julian Calendar still. I had to create another instance of Gregorian Calendar to fix the issue.

Calendar cal = new GregorianCalendar();
if (spanBegin == null) {
    cal.set(0000, Calendar.JANUARY, 1);
    spanBegin = cal.getTime();
}

Calendar cal = new GregorianCalendar();
if (spanEnd == null)
{
    cal.set(9999, Calendar.DECEMBER, 31);
    spanEnd = cal.getTime();
}

The question is, is the this an expected behavior or a bug on the date object? Actually using GregorianCalendar.getInstance() shows that the cdate is sometimes set to JulianCalendar.


Solution

  • What version of Java are you using and on what OS? Do you really need to store dates in the years 0 and 9999, or are you just using these as "negative infinity" and "positive infinity" values? How exactly do you see that the calendar is a Julian calendar?

    I tried this:

    Calendar cal = Calendar.getInstance();
    
    cal.set(0, Calendar.JANUARY, 1);
    Date d1 = cal.getTime();
    
    cal.set(9999, Calendar.DECEMBER, 31);
    Date d2 = cal.getTime();
    
    System.out.println(d1);
    System.out.println(d2);
    

    Output (on Windows XP, using Sun Java 1.6.0_16):

    Thu Jan 01 09:53:56 CET 1 java.util.Date
    Tue Dec 31 09:53:56 CET 9999 java.util.Date
    

    It changes the year 0 to the year 1. Changing the code to use a second Calendar object for the second date:

    Calendar cal = Calendar.getInstance();
    
    cal.set(0, Calendar.JANUARY, 1);
    Date d1 = cal.getTime();
    
    Calendar cal2 = Calendar.getInstance();
    cal2.set(9999, Calendar.DECEMBER, 31);
    Date d2 = cal2.getTime();
    
    System.out.println(d1);
    System.out.println(d2);
    

    This does not change anything to the output or the content of the two Date objects.

    Note: Beware that integer literals that start with a 0, such as 0000 in your code, will be interpreted as octal numbers by the Java compiler. That doesn't matter in this case because the number is 0, but you should not prepend integer literals with zeroes if you don't mean them as octal numbers.