What is the best way to convert a String
in the format 'January 2, 2010' to a Date
in Java?
Ultimately, I want to break out the month, the day, and the year as integers so that I can use
Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();
to convert the date into time.
Best Answer
That's the hard way, and those
java.util.Date
setter methods have been deprecated since Java 1.1 (1997). Moreover, the wholejava.util.Date
class was de-facto deprecated (discommended) since introduction ofjava.time
API in Java 8 (2014).Simply format the date using
DateTimeFormatter
with a pattern matching the input string (the tutorial is available here).In your specific case of "January 2, 2010" as the input string:
MMMM
pattern for itd
pattern for it.yyyy
pattern for it.Note: if your format pattern happens to contain the time part as well, then use
LocalDateTime#parse(text, formatter)
instead ofLocalDate#parse(text, formatter)
. And, if your format pattern happens to contain the time zone as well, then useZonedDateTime#parse(text, formatter)
instead.Here's an extract of relevance from the javadoc, listing all available format patterns:
G
u
y
D
M
/L
d
Q
/q
Y
w
W
E
e
/c
F
a
h
K
k
H
m
s
S
A
n
N
V
z
O
X
x
Z
Do note that it has several predefined formatters for the more popular patterns. So instead of e.g.
DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
, you could useDateTimeFormatter.RFC_1123_DATE_TIME
. This is possible because they are, on the contrary toSimpleDateFormat
, thread safe. You could thus also define your own, if necessary.For a particular input string format, you don't need to use an explicit
DateTimeFormatter
: a standard ISO 8601 date, like 2016-09-26T17:44:57Z, can be parsed directly withLocalDateTime#parse(text)
as it already uses theISO_LOCAL_DATE_TIME
formatter. Similarly,LocalDate#parse(text)
parses an ISO date without the time component (seeISO_LOCAL_DATE
), andZonedDateTime#parse(text)
parses an ISO date with an offset and time zone added (seeISO_ZONED_DATE_TIME
).Pre-Java 8
In case you're not on Java 8 yet, or are forced to use
java.util.Date
, then format the date usingSimpleDateFormat
using a format pattern matching the input string.Note the importance of the explicit
Locale
argument. If you omit it, then it will use the default locale which is not necessarily English as used in the month name of the input string. If the locale doesn't match with the input string, then you would confusingly get ajava.text.ParseException
even though when the format pattern seems valid.Here's an extract of relevance from the javadoc, listing all available format patterns:
G
y
Y
M
/L
w
W
D
d
F
E
u
a
H
k
K
h
m
s
S
z
Z
X
Note that the patterns are case sensitive and that text based patterns of four characters or more represent the full form; otherwise a short or abbreviated form is used if available. So e.g.
MMMMM
or more is unnecessary.Here are some examples of valid
SimpleDateFormat
patterns to parse a given string to date:yyyy.MM.dd G 'at' HH:mm:ss z
EEE, MMM d, ''yy
h:mm a
hh 'o''clock' a, zzzz
K:mm a, z
yyyyy.MMMM.dd GGG hh:mm aaa
EEE, d MMM yyyy HH:mm:ss Z
yyMMddHHmmssZ
yyyy-MM-dd'T'HH:mm:ss.SSSZ
yyyy-MM-dd'T'HH:mm:ss.SSSXXX
YYYY-'W'ww-u
An important note is that
SimpleDateFormat
is not thread safe. In other words, you should never declare and assign it as a static or instance variable and then reuse it from different methods/threads. You should always create it brand new within the method local scope.