将"2010年1月2日"格式的String
转换为Java格式的Date
的最佳方式是什么?
最终,我希望将月、日和年细分为整数,以便我可以使用
Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();
将日期转换为时间.
将"2010年1月2日"格式的String
转换为Java格式的Date
的最佳方式是什么?
最终,我希望将月、日和年细分为整数,以便我可以使用
Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();
将日期转换为时间.
这是一条艰难的道路,从Java1.1(1997)开始,这java.util.Date
个setter方法就被弃用了.此外,自从Java8(2014)引入java.time
API以来,整个java.util.Date
类实际上都被弃用(不推荐).
只需使用与输入字符串(the tutorial is available here)匹配的模式,使用DateTimeFormatter
格式化日期.
在"2010年1月2日"作为输入字符串的特定情况下:
MMMM
模式d
模式.yyyy
模式.String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02
注意:如果格式模式碰巧也包含时间部分,那么使用LocalDateTime#parse(text, formatter)
而不是LocalDate#parse(text, formatter)
.而且,如果您的格式模式碰巧也包含时区,则使用ZonedDateTime#parse(text, formatter)
.
以下是从the javadoc中摘录的相关信息,列出了所有可用的格式模式:
Symbol | Meaning | Presentation | Examples |
---|---|---|---|
G |
era | text | AD; Anno Domini; A |
u |
year | year | 2004; 04 |
y |
year-of-era | year | 2004; 04 |
D |
day-of-year | number | 189 |
M /L |
month-of-year | number/text | 7; 07; Jul; July; J |
d |
day-of-month | number | 10 |
Q /q |
quarter-of-year | number/text | 3; 03; Q3; 3rd quarter |
Y |
week-based-year | year | 1996; 96 |
w |
week-of-week-based-year | number | 27 |
W |
week-of-month | number | 4 |
E |
day-of-week | text | Tue; Tuesday; T |
e /c |
localized day-of-week | number/text | 2; 02; Tue; Tuesday; T |
F |
week-of-month | number | 3 |
a |
am-pm-of-day | text | PM |
h |
clock-hour-of-am-pm (1-12) | number | 12 |
K |
hour-of-am-pm (0-11) | number | 0 |
k |
clock-hour-of-am-pm (1-24) | number | 0 |
H |
hour-of-day (0-23) | number | 0 |
m |
minute-of-hour | number | 30 |
s |
second-of-minute | number | 55 |
S |
fraction-of-second | fraction | 978 |
A |
milli-of-day | number | 1234 |
n |
nano-of-second | number | 987654321 |
N |
nano-of-day | number | 1234000000 |
V |
time-zone ID | zone-id | America/Los_Angeles; Z; -08:30 |
z |
time-zone name | zone-name | Pacific Standard Time; PST |
O |
localized zone-offset | offset-O | GMT+8; GMT+08:00; UTC-08:00; |
X |
zone-offset 'Z' for zero | offset-X | Z; -08; -0830; -08:30; -083015; -08:30:15; |
x |
zone-offset | offset-x | +0000; -08; -0830; -08:30; -083015; -08:30:15; |
Z |
zone-offset | offset-Z | +0000; -0800; -08:00; |
请注意,对于更流行的模式,它有几个predefined formatters.所以你可以用DateTimeFormatter.RFC_1123_DATE_TIME
代替DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
.这是可能的,因为它们与SimpleDateFormat
相反,是线程安全的.因此,如果有必要,您也可以定义自己的.
对于特定的输入字符串格式,您不需要使用显式的DateTimeFormatter
:像2016-09-26T17:44:57Z这样的标准ISO 8601日期可以直接用LocalDateTime#parse(text)
进行解析,因为它已经使用了ISO_LOCAL_DATE_TIME
格式化程序.类似地,LocalDate#parse(text)
解析不带时间分量的ISO日期(参见ISO_LOCAL_DATE
),而ZonedDateTime#parse(text)
解析添加了偏移和时区的ISO日期(参见ISO_ZONED_DATE_TIME
).
如果您还没有使用Java8,或者被迫使用java.util.Date
,那么可以使用与输入字符串匹配的格式模式,使用SimpleDateFormat
来格式化日期.
String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010
请注意显式Locale
参数的重要性.如果省略它,则它将使用输入字符串的月份名称中使用的不一定是英语的default locale.如果区域设置与输入字符串不匹配,那么即使格式模式看起来有效,您也会得到令人困惑的java.text.ParseException
.
以下是从the javadoc中摘录的相关信息,列出了所有可用的格式模式:
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
G |
Era designator | Text | AD |
y |
Year | Year | 1996; 96 |
Y |
Week year | Year | 2009; 09 |
M /L |
Month in year | Month | July; Jul; 07 |
w |
Week in year | Number | 27 |
W |
Week in month | Number | 2 |
D |
Day in year | Number | 189 |
d |
Day in month | Number | 10 |
F |
Day of week in month | Number | 2 |
E |
Day in week | Text | Tuesday; Tue |
u |
Day number of week | Number | 1 |
a |
Am/pm marker | Text | PM |
H |
Hour in day (0-23) | Number | 0 |
k |
Hour in day (1-24) | Number | 24 |
K |
Hour in am/pm (0-11) | Number | 0 |
h |
Hour in am/pm (1-12) | Number | 12 |
m |
Minute in hour | Number | 30 |
s |
Second in minute | Number | 55 |
S |
Millisecond | Number | 978 |
z |
Time zone | General time zone | Pacific Standard Time; PST; GMT-08:00 |
Z |
Time zone | RFC 822 time zone | -0800 |
X |
Time zone | ISO 8601 time zone | -08; -0800; -08:00 |
请注意,模式区分大小写,四个或更多字符的基于文本的模式代表完整形式;否则,如果可用,则使用简短或缩写形式.因此,例如MMMMM
或更多是不必要的.
以下是迄今为止解析给定字符串的SimpleDateFormat
种有效模式的一些示例:
Input string | Pattern |
---|---|
2001.07.04 AD at 12:08:56 PDT | yyyy.MM.dd G 'at' HH:mm:ss z |
Wed, Jul 4, '01 | EEE, MMM d, ''yy |
12:08 PM | h:mm a |
12 o'clock PM, Pacific Daylight Time | hh 'o''clock' a, zzzz |
0:08 PM, PDT | K:mm a, z |
02001.July.04 AD 12:08 PM | yyyyy.MMMM.dd GGG hh:mm aaa |
Wed, 4 Jul 2001 12:08:56 -0700 | EEE, d MMM yyyy HH:mm:ss Z |
010704120856-0700 | yyMMddHHmmssZ |
2001-07-04T12:08:56.235-0700 | yyyy-MM-dd'T'HH:mm:ss.SSSZ |
2001-07-04T12:08:56.235-07:00 | yyyy-MM-dd'T'HH:mm:ss.SSSXXX |
2001-W27-3 | YYYY-'W'ww-u |
值得注意的是,SimpleDateFormat
是not线程安全的.换句话说,永远不要将其声明为静态变量或实例变量并将其赋值,然后从不同的方法/线程中重用它.您应该始终在本地范围内创建全新的方法.