Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calendar set YEAR issue

I tried the following piece of code:

Calendar c1 = Calendar.getInstance();
c1.set(Calendar.YEAR, 0);
c1.set(Calendar.DAY_OF_YEAR, 1);
Date d1 = c1.getTime();

Calendar c2 = Calendar.getInstance();
c2.setTime(d1);
c2.set(Calendar.YEAR, 2001);
c2.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c2.getTime().toString());

Calendar c3 = Calendar.getInstance();
c3.set(Calendar.YEAR, 2000);
c3.set(Calendar.DAY_OF_YEAR, 1);
Date d2 = c3.getTime();

Calendar c4 = Calendar.getInstance();
c4.setTime(d2);
c4.set(Calendar.YEAR, 2001);
c4.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c4.getTime().toString());

The result is:

Wed Jan 01 23:47:00 CET 2001
Mon Jan 01 23:47:00 CET 2001

What is wrong? Shouldn't I use Calendar in this way for setting YEAR?

like image 728
differenziale Avatar asked Nov 24 '11 22:11

differenziale


People also ask

What does calendar getInstance() return?

Calendar 's getInstance method returns a Calendar object whose calendar fields have been initialized with the current date and time: Calendar rightNow = Calendar.

Is calendar deprecated?

Calendar , too) are not officially deprecated, just declared as de facto legacy. The support of the old classes is still important for the goal of backwards compatibility with legacy code.

What is calendar set?

A calendar set is a group of calendars. You create a calendar set by defining a query that groups calendars according to the query result. Each calendar includes an availability type that determines how the events in the calendar are treated.


2 Answers

The year is relative to the era. By setting the year to something less or equal to 0 the calendar automatically corrects this by switching the era (from AD to BC or from BC to AD). This behaviour is better known from the other fields. E.g. if you set the month to something negative the year gets decremented accordingly.

Those corrections aren't made individually but rather they are made all at once, usually when you call getTime() to read out the resulting date.

Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
Date d1 = c1.getTime();               // January  1st,    1 BC (corrected)

Calendar c2 = Calendar.getInstance();
c2.setTime(d1);
c2.set(Calendar.YEAR, 2001);          // January  1st, 2001 BC
c2.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c2.getTime());     // prints "Wed Jan 01 05:35:00 CET 2001"
                                      // because 01/01/2001 BC was a Wednesday

So instead of setting the year to 2001 you would have to set it to -2000 (because year 0 doesn't exist at all). Or you could explicitly set the era:

c2.set(Calendar.ERA, GregorianCalendar.AD);

Another way to solve this "bug" is by not reading out the time before the complete date is set:

Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
c1.set(Calendar.YEAR, 2001);          // January  1st, 2001 AD
System.out.println(c1.getTime());     // prints the expected date

To output the era of a date you can use "G" in the pattern of a SimpleDateFormat:

new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy G").format(c2.getTime())
// "Wed Jan 01 05:35:00 CET 2001 BC"
like image 84
Robert Avatar answered Oct 01 '22 16:10

Robert


In both cases, immediately prior to printing your output, you set the year to 2001. In both cases, the output reflected that year. Were you expecting a different output?

like image 45
phatfingers Avatar answered Oct 01 '22 16:10

phatfingers