Given the following code:
[...]
public void testFormatDateString() throws ParseException {
String dateString = new java.util.Date().toString();
System.out.println(dateString);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z YYYY", Locale.ENGLISH);
Date date = format.parse(dateString);
System.out.println(date.toString());
}
[...]
Before:
Sat Aug 19 18:26:11 BST 2017
After:
Sat Jan 07 17:26:11 GMT 2017
Why is the date changed?
The upper case Y
is for "week year", which has 364 or 371 days instead of the usual 365 or 366. With lower case y
(which is used by Date#toString
) everything works as expected:
public void testFormatDateString() throws ParseException {
String dateString = new java.util.Date().toString();
System.out.println(dateString);
// Force to Locale.US as this is hardcoded in Date#toString
SimpleDateFormat format = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss z yyyy", Locale.US);
Date date = format.parse(dateString);
System.out.println(date.toString());
}
Output:
Sat Aug 19 17:50:39 GMT 2017
Sat Aug 19 17:50:39 GMT 2017
See on ideone.com
As mentioned in the comments, make sure to include Locale.US
when parsing the dateString
, as that is hardcoded in Date#toString
. See this question for details.
The first of all I would say that I completely agree with Marvins answer but I hope someone will be interested in more technical details.
Following java doc for SimpleDateFormat
you can't find example with YYYY
. But it works and validation is passed. Checking deeper:
public class SimpleDateFormat extends DateFormat {
//....
/**
* Returns the compiled form of the given pattern. The syntax of
* the compiled pattern is:
* <blockquote>
* CompiledPattern:
* EntryList
* EntryList:
* Entry
* EntryList Entry
* Entry:
* TagField
* TagField data
* TagField:
* Tag Length
* TaggedData
* Tag:
* pattern_char_index
* TAG_QUOTE_CHARS
* Length:
* short_length
* long_length
* TaggedData:
* TAG_QUOTE_ASCII_CHAR ascii_char
*
* </blockquote>
* ....
*
* @exception NullPointerException if the given pattern is null
* @exception IllegalArgumentException if the given pattern is invalid
*/
private char[] compile(String pattern) {
...
if ((tag = DateFormatSymbols.patternChars.indexOf(c)) == -1) {
throw new IllegalArgumentException("Illegal pattern character " +
"'" + c + "'");
}
...
}
...
}
Checking allowed pattern symbols (that used in validation condition) DateFormatSymbols.patternChars
:
public class DateFormatSymbols implements Serializable, Cloneable {
...
static final String patternChars = "GyMdkHmsSEDFwWahKzZYuXL";
...
}
Y
is valid pattern element, what's it means (lets check constants in same DateFormatSymbols
class)?
static final int PATTERN_ERA = 0; // G
static final int PATTERN_YEAR = 1; // y
static final int PATTERN_MONTH = 2; // M
static final int PATTERN_DAY_OF_MONTH = 3; // d
static final int PATTERN_HOUR_OF_DAY1 = 4; // k
static final int PATTERN_HOUR_OF_DAY0 = 5; // H
static final int PATTERN_MINUTE = 6; // m
static final int PATTERN_SECOND = 7; // s
static final int PATTERN_MILLISECOND = 8; // S
static final int PATTERN_DAY_OF_WEEK = 9; // E
static final int PATTERN_DAY_OF_YEAR = 10; // D
static final int PATTERN_DAY_OF_WEEK_IN_MONTH = 11; // F
static final int PATTERN_WEEK_OF_YEAR = 12; // w
static final int PATTERN_WEEK_OF_MONTH = 13; // W
static final int PATTERN_AM_PM = 14; // a
static final int PATTERN_HOUR1 = 15; // h
static final int PATTERN_HOUR0 = 16; // K
static final int PATTERN_ZONE_NAME = 17; // z
static final int PATTERN_ZONE_VALUE = 18; // Z
static final int PATTERN_WEEK_YEAR = 19; // Y
static final int PATTERN_ISO_DAY_OF_WEEK = 20; // u
static final int PATTERN_ISO_ZONE = 21; // X
static final int PATTERN_MONTH_STANDALONE = 22; // L
and here you can find the Y
pattern element (the name is readable clear):
static final int PATTERN_WEEK_YEAR = 19; // Y
*_WEEK_YEAR
provides some confuse if we expecting single YEAR
(following naming convention PATTERN_YEAR
). Also we can find
static final int PATTERN_YEAR = 1; // y
Difference of meaning we can search in internet (in wiki for example). But what is the difference of using it in code? Continuing the check of using constants in SimpleDateFormat
we can detect that PATTERN_WEEK_YEAR
and PATTERN_YEAR
are used in similar way for almost all cases. But with small logical difference (just find elements using in DateFormatSymbols.java
)... and as result we'll be sure that code provides same to wiki terming meaning.
...following this java investigation way (using java doc and sources) we can clarify almost all questions without additional help with getting deep JDK
knowledges.
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