This started as a simple error: I had YYYY
instead of yyyy
in my format string for a SimpleDateFormat
object. But I'm totally baffled by the results of my tests with the incorrect format string.
This code:
@Test public void whatTheHell() { try { SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/YYYY"); Date d1 = sdf.parse("01/07/2016"); Date d2 = sdf.parse("02/08/2016"); Date d3 = sdf.parse("11/29/2027"); System.out.println(d1.toString()); System.out.println(d2.toString()); System.out.println(d3.toString()); } catch (ParseException pe) { fail("ParseException: " + pe.getMessage()); } }
produces this output:
Sun Dec 27 00:00:00 PST 2015 Sun Dec 27 00:00:00 PST 2015 Sun Dec 27 00:00:00 PST 2026
I've read the documentation on the 'Y' parameter here: https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html, but I still can't see the logic that's working here. Particularly the last instance: I can kinda-sorta understand how the dates in January (& maybe February) can be translated into December of the previous year, but moving the date of November 29th backwards by 11 months baffles me. And what's so special about December 27th?
Can anyone explain?
MORE INFORMATION
@Jan suggested that relying on the toString() method could be a problem, so I defined a date format to print YYYY MM dd '-' yyyy MM dd
in the same code as above. Here is the additional output:
2016 12 27 - 2015 12 27 2016 12 27 - 2015 12 27 2027 12 27 - 2026 12 27
In some languages, such as Java, the symbols are case-sensitive. While a lower-case yyyy is the year, an upper-case YYYY is the week year. The current week year is usually the same as the current calendar year.
In a week-based-year, each week belongs to only a single year. Week 1 of a year is the first week that starts on the first day-of-week and has at least the minimum number of days. The first and last weeks of a year may contain days from the previous calendar year or next calendar year respectively.
It's simple: December 27 2015 is day 1 of week 1 of week-year 2016 (and December 27 2026 is day 1 of week 1 of week-year 2027). This can be verified by adding these lines:
SimpleDateFormat odf = new SimpleDateFormat("YYYY-ww-u"); System.out.println(odf.format(d1)); System.out.println(odf.format(d2)); System.out.println(odf.format(d3));
If a SimpleDateFormat
outputs a date it can use all fields: year, month, day, day of week, week of month, week in year, week-year etc.
On parsing, SimpleDateFormat
expects a matching set of values: either day, month, year or day of week, week in year, week-year. Since you supplied a week-year but did not supply day of week and week in year, those to values have been assumed as 1.
The actual values depend on your locale:
(see https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_and_year)
On my system (using de-ch locale, with "EEE MMM dd HH:mm:ss zzz yyyy - YYYY-ww-u" as format) I get
Mo Jan 04 00:00:00 MEZ 2016 - 2016-01-1 Mo Jan 04 00:00:00 MEZ 2016 - 2016-01-1 Mo Jan 04 00:00:00 MEZ 2027 - 2027-01-1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With