Converting a string to a date in Java (or any programming language) is a fundamental skill and is useful to know when working on projects. Sometimes, it's simply easier to work with a string to represent a date, and then convert it into a Date
object for further use.
In this article, we'll go over the many methods and libraries you can use to convert a Java string into a date object.
The Date/Time API
The Date/Time API in Java works with the ISO 8601 format by default, which is (yyyy-MM-dd)
.
All Dates by default follow this format, and all Strings that are converted must follow it if you're using the default formatter.
parse()
This API defines a parse()
method that accepts a sequence of characters and uses the ISO_LOCAL_DATE
format to parse the input:
parse(CharSequence);
Alternatively, you can use the two-argument variant of this method, defining a different formatter:
parse(CharSequence, DateTimeFormatter);
A DateTimeFormatter
is used for formatting and parsing date-time objects in the new Date/Time API. All date-time classes from this API contain a method for parsing and formatting, where each accepts a DateTimeFormatter to define a pattern.
Converting a String to LocalDate
A LocalDate
represents a date, without time in ISO-8601 format.
It differs from Date
in the fact that it doesn't store time as a millisecond offset since epoch, but rather simply the current date. It's also a newer implementation from the Date/Time API and offers its own format/parse method, as well as addition and subtraction of days, weeks and years, which doesn't exist in the Date variant.
To convert a string to a LocalDate
object, it's enough to write:
LocalDate date = LocalDate.parse("2018-09-16");
This is the equivalent of writing the proceeding code to instantiate a LocalDate
object:
LocalDate date = LocalDate.of(2018, 09, 16);
Converting a String to LocalTime
LocalTime
represents time, without a time-zone in ISO-8601 format. It doesn't store time based on the offset since epoch, and it offers nanosecond precision.
Just like the LocalDate, it provides a lot of very useful parsing and formatting methods built in, as well as the means to add or subtract time from it.
To convert a string to a LocalTime
object, it's enough to write:
LocalTime localTime = LocalTime.parse("8:00");
This is the equivalent of writing the proceeding code to instantiate a LocalTime
object:
LocalTime localTime = LocalTime.of(8, 00);
Converting a String to LocalDateTime
The LocalDateTime
is the most used class regarding Date/Time in Java. It represents a combination of date and time, and can be used for many purposes:
LocalDateTime localDateTime = LocalDateTime.parse("2018-09-16T08:00:00");
This format may seem confusing at first, but it's actually rather simple:
The "Time" marker simply represents a line between the LocalDate
and LocalTime
parts of the format.
You can also easily format this LocalDateTime
into a more readable format:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatDateTime = localDateTime.format(formatter);
Running this piece of code and printing formatDateTime
would yield:
2018-09-16 08:00:00
You would typically do this to show the result to the end user in string format, while performing operations on the LocalDateTime
object beforehand.
Converting a String to ZonedDateTime
Depending on the project you're working on you might need to handle different time zones when dealing with dates and time.
Converting a String to a ZonedDateTime
object is as simple as:
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2018-09-16T08:00:00+00:00[Europe/London]");
The example above shows how you would initialize a ZonedDateTime
for London.
Converting a String using a Custom Formatter
Sometimes, we could wish to use our own custom formatter, that accepts a string in the most varied ways and still not throw a DateTimeParseException
.
Here are some of the most common patterns you would use:
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
y
: Year (2018, 18)M
: Month in a year (August, Aug, 08)d
: Day in a month (1, 5, 25)E
: Name of a day in a week (Monday, Saturday)a
: Ante meridiem/Post meridiem marker (AM, PM)H
: Hour in a 24h style (1, 7, 14, 21)h
: Hour in a 12h style (1, 5, 12)m
: Minute in an hour (1, 25, 54)s
: Second in a minute (1, 25, 54)
And some you might not use that often:
G
: Era designator (AD, CE)Y
: Week year (2018, 18)w
: Week in a a year (25, 53)W
: Week in a month (2)D
: Day in a year (254)F
: Day of week in a month (3)E
: Day name in a week (Monday, Mon)u
: Day number of a week (1, 4)k
: Hour in a day (17)K
: Hour in a day in AM/PM (5)S
: Millisecond (1245)z
: General Time Zone (Pacific Standard Time;PST;GMT-8:00)Z
: RFC 822 Time Zone (-0800)X
: ISO 8601 Time Zone (-08, -0800, -8:00)
Note: Week year differs from a year - A week year is in sync with a WEEK_OF_YEAR
cycle. All weeks between the first and last weeks (inclusive) have the same week year value. Therefore, the first and last days of a week year may have different calendar year values.
Note: K
and H
differ the same way k
and h
differ. H
and h
refer to the 0-23 and 1-12 model respectively, while K
and k
refer to the 0-11 and 1-24 respectively.
If this still doesn't satisfy your need for a custom formatter, you can use DateTimeFormatterBuilder to build very specific and complex formatters. Amongst other things, DateTimeFormatter is built using this class.
java.util.Date
This is an older approach, which isn't used often today, but it's still worth covering since sometimes we still use the classes from these APIs:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Date date = formatter.parse("22-Sep-2018");
There are many patterns that we can pass into the constructor of SimpleDateFormat
. You can combine pretty much any number of formats using the available patterns.
It's not possible to set a timezone for a Date, because it simply doesn't contain such information. However, it's easy to format the date and add the timezone information to a String:
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse("22-09-2018 08:23:43 PM");
String formattedDate = formatter.format(date);
System.out.println(date);
System.out.println(formattedDate);
Running this piece of code will yield:
Sat Sep 22 22:23:43 CEST 2018
22-9-2018 08:23:43 PM
"22:23:43 CEST" corresponds to the "10:23:43PM" time, while the formatted date represents "8:23:43 PM" since it's in a different time zone.
SimpleDateFormat vs DateTimeFormatter
Reading this article, it's fair to raise the question - "What is the difference, and which one should I be using?"
DateTimeFormatter
has been added in Java 8 with the new Date/Time API, and replaces the older, now less frequently used SimpleDateFormat
. It's thread-safe unlike its older counterpart and offers new functionality:
// SimpleDateFormat
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy");
Date date = new Date();
String formattedDate = formatter.format(date);
Date parsedDate = formatter.parse(formattedDate);
// DateTimeFormatter
LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-M-yyyy");
String formattedDate = date.format(formatter);
LocalDate parsedDate = LocalDate.parse(formattedDate, formatter);
It's clear to see the difference between these two. In the older way, a formatter is used to format and then parse the date. In the newer way, dates have their own format and parse methods and use a DateTimeFormatter
simply for the pattern.
If you're using Java 8 and the new API, use DateTimeFormatter, whereas if you're still using an older version of Java, use SimpleDateFormat.
Joda-Time
Joda-Time was developed to counter the problems with the old Java time and date classes.
As of Java 8, these problems have been corrected, and Joda-Time has served its purpose. Even the authors of it advise migrating to official java.time
to work with dates and time.
In the case that this is impossible, and for those who still use a version of Java prior to Java 8, Joda-Time is still a great library to use.
A dependency for this library can easily be added with a Maven dependency:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>{version}</version>
</dependency>
Working with Joda-Time is very similar to working with Java's Date/Time API:
DateTimeFormatter formatter = DateTimeFormatter.forPattern("dd-MM-yyyy HH:mm:ss");
DateTime dateTime = DateTime.parse("22-Sep-2018 8:15:43", formatter);
Joda-Time's DateTime
class supports timezones as well:
DateTimeFormatter formatter = DateTimeFormatter.forPattern("dd-MM-yyyy HH:mm:ss");
DateTime dateTime = DateTime.parse("22-Sep-2018 8:15:43", formatter);
DateTime dateTimeZoned = dateTime.withZone(DateTimeZone.forID("Europe/London));
For a full list of time zone IDs available for use, visit the official docs.
Apache Commons
Apache Commons is a useful library used in many projects.
To add this library to your project, you can use the Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>{version}</version>
</dependency>
Both of the implementations below accept an array of patterns. These methods will parse each pattern after another. If no pattern matches the input string, a ParseException
is thrown.
Using DateTimeConverter
DateTimeConverter dtc = new DateConverter();
dtc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd hh:mm:ss" });
ConvertUtils.register(dtc, Date.class);
Using DateUtils
Date date = DateUtils.parseDate("22-Sep-2018", String[] {"dd-MM-yyyy HH:mm:ss", "dd-MM-yyyy"});
Conclusion
We've covered multiple ways to convert a simple String into Date and Date-Time classes in Java. Some of these approaches utilize third-party libraries which you might already have in your project, and some are done utilizing the APIs Java offers.