[英]Why is SimpleDateFormat changing the date?
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
之前:
Sat Aug 19 18:26:11 BST 2017
After: Sat Jan 07 17:26:11 GMT 2017
之后:
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: 大写
Y
代表“周年” ,它有364或371天而不是通常的365或366.小写y
(由Date#toString
)一切都按预期工作:
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 请参阅ideone.com
As mentioned in the comments, make sure to include Locale.US
when parsing the dateString
, as that is hardcoded in Date#toString
. 正如评论中所提到的,确保在解析
dateString
时包含Locale.US
,因为它在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. 首先,我会说我完全同意Marvins的回答,但我希望有人会对更多技术细节感兴趣。
Following java doc for SimpleDateFormat
you can't find example with YYYY
. 在使用
SimpleDateFormat
java doc之后 ,您无法找到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
: 检查允许的模式符号(在验证条件中使用)
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)? Y
是有效的模式元素,它意味着什么(让我们在同一个DateFormatSymbols
类中检查常量)?
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): 在这里你可以找到
Y
模式元素(名称可读清晰):
static final int PATTERN_WEEK_YEAR = 19; // Y
*_WEEK_YEAR
provides some confuse if we expecting single YEAR
(following naming convention PATTERN_YEAR
). *_WEEK_YEAR
如果我们期望单个YEAR
(遵循命名约定PATTERN_YEAR
), *_WEEK_YEAR
提供一些混淆。 Also we can find 我们也可以找到
static final int PATTERN_YEAR = 1; // y
Difference of meaning we can search in internet (in wiki for example). 我们可以在互联网上搜索的意义差异(例如在wiki中)。 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. 继续检查在
SimpleDateFormat
中使用常量,我们可以检测到几乎所有情况都以类似的方式使用PATTERN_WEEK_YEAR
和PATTERN_YEAR
。 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. 但是逻辑差异很小(只是在
DateFormatSymbols.java
找到元素)......结果我们将确保代码提供相同的wiki术语含义。
...following this java investigation way (using java doc and sources) we can clarify almost all questions without additional help with getting deep JDK
knowledges. ...遵循这种java调查方式(使用java doc和sources),我们可以澄清几乎所有问题,而无需获得深入的
JDK
知识的额外帮助。
It is actually the same date, British Summer Time (BST) is exactly one hour ahead of GMT. 实际上是同一天,英国夏令时(BST)比格林威治标准时间提前一小时。
Note also that 'Y' is the Week of the year, What you want to use is 'y' 另请注意,'Y'是一年中的一周,您想要使用的是'y'
https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.