0

I have a date String in this format "YYYY-MM-dd HH::mm:ss". Every time i parse the string i get wrong date.("Sun Dec 29 10:10:10 CET 2013"). The code is below:

DateFormat timeFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date startDate = timeFormat.parse("2014-08-10 10:10:10");
System.out.println(startDate);

This returns "Sun Dec 29 10:10:10 CET 2013". How to correctly parse the date String?

user506246
  • 301
  • 1
  • 4
  • 15
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html), and `java.text.SimpleTextFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jun 08 '17 at 10:08

2 Answers2

2

Rather than using YYYY you will need to use yyyy.

Y Refers to WEEK_YEAR whereas y refers to YEAR. WEEK_YEARs are based on when the first full week of a year starts (this differs depending on settings), and thus are slightly (and sometimes largely) different from that of YEAR.

See the javadoc: http://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_year

Zwander
  • 382
  • 2
  • 12
0

You are using wrong format. You need yyyy instead of YYYY.

If you take a look at SimpleDateFormat documentation you will find that

y   Year
Y   Week year

where "week year" is in sync with a WEEK_OF_YEAR cycle.

Now, why YYYY returns 2013 for year 2014?

To answer this question you need to understand how calendar determines that week belongs to some year. Rule is quite simple:

  • week belongs to year XXXX if last N days of this week (usually N=4 but it is determined by getMinimalDaysInFirstWeek from used Calendar) belongs to year XXXX
  • weeks starts at day which is result from getFirstDayOfWeek. This result depends on Locale but in next examples we will use Monday as first day of week.

Example 1.

Assuming that first day of week is Monday and days required for week to belong to some year is 4 lets try to determine which week is first in year XXXX for January which looks like this:

       January XXXX
Mon Tue Wed Thu Fri Sat Sun 
 27  28  29  30  31   1   2
  3   4   5   6   7   8   9
...

Week from first row contains only two days which belongs to year XXXX (to January), 1st and 2nd

 27  28  29  30  31   1   2
                    ^^^ ^^^  //days which belong to January

but this is less than number of days required for this week to belong to XXXX year while next week

  3   4   5   6   7   8   9

contains 7 days which belong to XXXX year. Since week in first row doesn't belong to year XXXX first week in week year will start 3 January XXXX. This means that if we parse value XXXX with format YYYY we will get 3rd January XXXX.

Example 2.

Now lets say that calendar for year XXXX looks like this

       January XXXX
Mon Tue Wed Thu Fri Sat Sun 
 30  31   1   2   3   4   5
  6   7   8   9  10  11  12
...

As you can see in week

 30  31   1   2   3   4   5

its last 5 days belong to year XXXX which is more than required 4 days
-> which means that this week belongs to year XXXX,
-> and it is also first week of XXXX year
-> which means that first week of this year starts at 30 December (XXXX-1)
-> which finally means that if you parse such year using YYYY format you will get value XXXX-1.


Example 2 is actually situation from year 2014, which is why year was interpreted as year 2013.

BTW, if you would decide to use format with week year to set month and day you would also need to use special formats which would describe

  • which week of year you want to set
  • and which day of week

so instead of M and d you would have to use

w   Week in year
u   Day number of week (1 = Monday, ..., 7 = Sunday)

(hours, minutes, seconds are part of time rather than date so H m and s are fine in this format)

for instance

DateFormat format = new SimpleDateFormat("YYYY-ww-uu HH:mm:ss");
Date date = format.parse("2004-53-7 10:10:10");
System.out.println(date);

which will be parsed to Sun Jan 02 10:10:10 CET 2005

Pshemo
  • 122,468
  • 25
  • 185
  • 269