0

I hope it's not a JDK bug, or I am tempted to cash all my bank accounts and throw it in a mattress... Here is the code. Please note that setting the date to Dec.29 immediately rolls the year to 2020. Also, the toString() output reveals that Calendar seems to think the week number is "1".

import java.util.*; // headers MUST be above the first class
import java.text.*;

public class JDKCalendarBug {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-YYYY kk:mm");
        Calendar cal = java.util.Calendar.getInstance(TimeZone
                .getTimeZone("EST"));
        cal.clear();
        cal.set(Calendar.YEAR, 2019);
        cal.set(Calendar.MONTH, Calendar.DECEMBER);

        cal.set(Calendar.DAY_OF_MONTH, 26);
        Date t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 27);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 28);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 29);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

    }

}

Output:

12-26-2019 24:00 java.util.GregorianCalendar[time=1577336400000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=2019,MONTH=11,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=26,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=?,HOUR=?,HOUR_OF_DAY=?,MINUTE=?,SECOND=?,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

12-27-2019 24:00 java.util.GregorianCalendar[time=1577422800000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=4,DAY_OF_MONTH=27,DAY_OF_YEAR=361,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0] 12-28-2019 24:00 java.util.GregorianCalendar[time=1577509200000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=4,DAY_OF_MONTH=28,DAY_OF_YEAR=362,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0]

12-29-2020 24:00 java.util.GregorianCalendar[time=1577595600000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=29,DAY_OF_YEAR=363,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0]

stud3nt
  • 2,056
  • 1
  • 12
  • 21
  • Do you have information about your JDK and your Locale settings? Depending on your locale a weeknumber can be 1 or 52 in the last week of a year. Your locale also decides the weeknumber of 29 december – FredvN Dec 17 '19 at 16:50
  • jre1.8.0_231: came packaged with Eclipse. Following your lead I re-ran the code using "Locale.US", bu tgot the same result. Thank you for your reply, Fred! – Alex Yershov Dec 17 '19 at 18:08
  • Does this answer your question? [Y returns 2012 while y returns 2011 in SimpleDateFormat](https://stackoverflow.com/questions/8686331/y-returns-2012-while-y-returns-2011-in-simpledateformat) – Ole V.V. Dec 28 '19 at 07:38
  • I recommend you don’t use `Calendar`, `Date`, `TimeZone` and `SimpleDateFormat`. Those classes are poorly designed and long outdated, the last in particular notoriously troublesome. Instead use `ZoneId` `ZonedDateTime` and `DateTimeFormatter`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Dec 28 '19 at 07:45

1 Answers1

1

The problem is with SimpleDateFormat. If you change your format string to lowercase ys the date formats correctly as 12-29-2019 24:00

new SimpleDateFormat("MM-dd-yyyy kk:mm")

The Y corresponds to the "Week Year", which is different than "Year" and not always supported in all calendars. According to the JavaDocs:

If week year 'Y' is specified and the calendar doesn't support any week years, the calendar year ('y') is used instead. The support of week years can be tested with a call to getCalendar().isWeekDateSupported().

In this case, "week year" is supported as the underlying Calendar implementation is GregorianCalendar. According to the its JavaDocs:

A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between the first and last weeks (inclusive) have the same week year value. Therefore, the first and last days of a week year may have different calendar year values.

bdkosher
  • 5,753
  • 2
  • 33
  • 40
  • yyyy is the calendar year, YYYY is the year of het weeknumber of the date. In the first and last week of a year this two can be different – FredvN Dec 17 '19 at 18:57
  • You're right, I was looking at older JavaDocs and `Y` wasn't a supported symbol, leading to my confusion. – bdkosher Dec 17 '19 at 18:58