String to date conversion is one of the most frequent tasks in Java or any other programming language. It is useful to know how to perform string to date conversion before working on Java projects.

In this tutorial, you'll learn about different ways to convert a string object to a date object in Java. We'll first look at utility methods provided by Java 8 new date and time API to perform string to date conversion. Afterward, we'll also look at the legacy java.util.Date class that is also used to represent dates. Finally, we'll discuss 3rd-party libraries like Apache Commons Lang that can also be used to perform this conversion.

Java 8 Date & Time API

Java 8 introduced a new date and time API (classes in java.time.* package) to make it easier to work with dates in Java. By default, these classes use ISO-8601 format to represent dates and times.

parse() Method

The new API provides the parse() method that accepts a sequence of characters as an argument and uses the ISO_LOCAL_DATE format to parse the string into a date:

parse(CharSequence text)

To convert a string into an instance of date using the above method, the string must be in ISO-8601 format. Otherwise, a DateTimeParseException will be thrown at runtime.

Alternatively, you can pass another parameter to parse() to explicitly define the string pattern:

parse(CharSequence text, DateTimeFormatter formatter)

A DateTimeFormatter instance is used as a formatter for formatting and parsing date-time objects in Java 8 new date and time API.

Convert String to LocalDate

The LocalDate class represents a date in ISO-8601 format (yyyy-MM-dd) without any time information. It is different from the old Date in the fact that it doesn't store time or timezone information. Unlike Date, LocalDate provides utility methods to parse and format dates, add or subtract different units like days, months, and years.

To parse an ISO-8601 string to an instance of LocalDate, you can do the following:

// ISO-8601 string
String str = "2019-12-22";

// parse string to date
LocalDate date = LocalDate.parse(str);

The above code is equivalent of writing the following code to instantiate a LocalDate instance:

LocalDate date = LocalDate.of(2019, Month.DECEMBER, 22);

If the string is not in ISO-8601 format, you must define a custom formatter using DateTimeFormatter as shown below:

// custom string format
String customStr = "December 22, 2019";

// define formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy");

// parse string to date
LocalDate customDate = LocalDate.parse(customStr, formatter);

Here is another example that uses the pre-defined formatter BASIC_ISO_DATE from DateTimeFormatter to parse a string into a LocalDate:

// string in basic ISO-8601 format
String str = "20191222";

// parse string to date
LocalDate date = LocalDate.parse(str, DateTimeFormatter.BASIC_ISO_DATE);

Convert String to LocalTime

A LocalTime instance represents a time, without the date or timezone information in ISO-8601 format. Just like LocalDate, you can use LocalTime.parse() method to convert a string to a LocalTime object as shown below:

// ISO-8601 string
String str = "08:45";

// parse string to time
LocalTime time = LocalTime.parse(str);

The above code is equivalent of writing the following code to instantiate an instance of LocalTime:

LocalTime time = LocalTime.of(8, 45);

For non ISO-8601 string formats, you have to pass a formatter using DateTimeFormatter as shown below:

// custom string format
String customStr = "10:15 PM";

// define formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a");

// parse string to time
LocalTime customTime = LocalTime.parse(customStr, formatter);

Convert String to LocalDateTime

The LocalDateTime class is the most popular class for handling date and time together in Java 8 and higher. It stores a combination of date and time without timezone in ISO-8601 format (yyyy-MM-ddTHH:mm).

To parse an ISO-8601 string into an instance of LocalDateTime, you can simply use the parse() method as shown below:

// ISO-8601 string
String str = "1989-08-02T11:25";

// parse string to date and time
LocalDateTime dateTime = LocalDateTime.parse(str);

The above code is equivalent to the following code that instantiates an instance of LocalDateTime:

LocalDateTime dateTime = LocalDateTime.of(1989, Month.AUGUST, 2, 11, 25); 

To convert a string with a custom date format into a LocalDateTime object, you need to supply a formatter using DateTimeFormatter:

// custom string format
String customStr = "07/17/2018 12:45 PM";

// define formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a");

// parse string to date and time
LocalDateTime customDT = LocalDateTime.parse(customStr, formatter);

Convert String to ZonedDateTime

The ZonedDateTime class is used to deal with timezone specific dates and times. It represents a date-time with a timezone in the ISO-8601 format (e.g. 2010-05-15T10:15:30+01:00[Europe/Paris]).

To convert an ISO-8601 string into an instance of ZonedDateTime, just use the parse() method:

// ISO-8601 string
String str = "2010-05-15T10:15:30+01:00[Europe/Paris]";

// parse string to zoned date and time
ZonedDateTime dateTime = ZonedDateTime.parse(str);

Convert String to OffsetDateTime

The OffsetDateTime class represents a date and time with an offset from UTC/Greenwich in the ISO-8601 format (e.g. 1992-06-30T23:15:30-03:30).

The following example demonstrates how you can convert an ISO-8601 string into an instance of OffsetDateTime:

// ISO-8601 string
String str = "1992-06-30T23:15:30-03:30";

// parse string to offset date and time
OffsetDateTime dateTime = OffsetDateTime.parse(str);

To parse custom strings into OffsetDateTime, you need to parse a custom formatter using DateTimeFormatter as shown below:

// custom string format
String customStr = "Mon, July 15, 2019 10:00 AM +03:00";

// define formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, MMMM dd, yyyy hh:mm a XXX");

// parse string to offset date and time
OffsetDateTime customDT = OffsetDateTime.parse(customStr, formatter);

Convert String to Instant

The Instant class represents a specific moment on the timeline. To convert a string into an Instant object, the string must be in ISO_INSTANT format (e.g. 2011-12-03T10:15:30Z).

Here is an example:

// ISO-8601 string
String str = "2011-12-03T10:15:30Z";

// parse string to instant
Instant instant = Instant.parse(str);

You can easily convert an Instant object to any other date-time format like LocalDateTime or ZonedDateTime:

// convert instant to local date-time
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId()));
System.out.println(localDateTime);

// convert instant to zoned date-time
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Karachi"));
System.out.println(zonedDateTime);

Here is the output of the above code snippet:

2011-12-03T10:15:30
2011-12-03T15:15:30+05:00[Asia/Karachi]

Look at Introduction to Java 8 Date and Time API guide for more new date and time API examples.

Convert String to java.util.Date

Before Java 8, both java.util.Date and java.util.Calendar classes were used to handle dates and times. These classes are not actively used today but they are still worth covering as most of the legacy codes are still using them.

To convert a string into an instance of Date, you need to use the SimpleDateFormat class to define a custom date and time pattern. Here are a few examples:

try {
    // different data-time strings
    String str1 = "10/23/2011";
    String str2 = "10-Jan-2015";
    String str3 = "Fri, August 3 2018";
    String str4 = "Friday, Jun 07, 2019 10:10:56 AM";
    String str5 = "2018-10-05T15:23:01Z";

    // define date-time patterns
    SimpleDateFormat sdf1 = new SimpleDateFormat("MM/dd/yyyy");
    SimpleDateFormat sdf2 = new SimpleDateFormat("dd-MMM-yyyy");
    SimpleDateFormat sdf3 = new SimpleDateFormat("EEE, MMMM d yyyy");
    SimpleDateFormat sdf4 = new SimpleDateFormat("EEEE, MMM dd, yyyy hh:mm:ss a");
    SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");

    // convert string to dates
    System.out.println(sdf1.parse(str1));
    System.out.println(sdf2.parse(str2));
    System.out.println(sdf3.parse(str3));
    System.out.println(sdf4.parse(str4));
    System.out.println(sdf5.parse(str5));

} catch (ParseException ex) {
    ex.printStackTrace();
}

The above code generates the following output:

Sun Oct 23 00:00:00 PKT 2011
Sat Jan 10 00:00:00 PKT 2015
Fri Aug 03 00:00:00 PKT 2018
Fri Jun 07 10:10:56 PKT 2019
Fri Oct 05 20:23:01 PKT 2018

By default, Date doesn't contain any information about the timezone. Therefore, it is not possible to set a timezone for a Date object. When we convert a string to Date using SimpleDateFormat.parse(), it is automatically converted to the default system timezone.

For example, look at the last string to date conversion in the example above. The 2018-10-05T15:23:01Z date-time string in UTC (with time 15:23:01) is converted to Fri Oct 05 20:23:01 PKT 2018 with time 20:23:01. This is because the PKT is 5 hours ahead of UTC (+05:00).

However, you can format the Date object and add the timezone information to a string using SimpleDateFormat:

try {
    // date-time string
    String str = "2018-10-05T15:23:01Z";

    // define date-time pattern
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");

    // set Europe/Paris timezone
    formatter.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));

    // convert string to date
    Date date = formatter.parse(str);

    // format date to string with timezone
    String zonedDate = formatter.format(date);

    // print dates
    System.out.println(date);
    System.out.println(zonedDate);

} catch (ParseException ex) {
    ex.printStackTrace();
}

Here is the output of the above code:

Fri Oct 05 20:23:01 PKT 2018
2018-10-05T17:23:01+02

DateTimeFormatter vs SimpleDateFormat

After learning string to date conversion through both Java 8 new date and time API's DateTimeFormatter and SimpleDateFormat, you may be wondering "how do they differ from each other, and what is the right choice for me?"

Introduced in Java 8 with the new date and time API, DateTimeFormatter is a part of java.time.format.* that replaces the older and less frequently used SimpleDateFormat. Both these classes are used to declare a date and time pattern for parsing and formatting dates and times.

The DateTimeFormatter class is thread-safe unlike its older counterpart and offers new utility methods and constants for various date and time formats.

Let us look at the below example:

// `DateTimeFormatter` example
LocalDate localDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
String localDateStr = localDate.format(formatter);
LocalDate parsedLocalDate = LocalDate.parse(localDateStr, formatter);

// `SimpleDateFormat` example
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
String dateStr = sdf.format(date);
Date parseDate = sdf.parse(dateStr);

As you can see above, the difference between DateTimeFormatter and SimpleDateFormat is very much clear. In the new date and time API, the classes have their own parse and format methods and use DateTimeFormatter for the sake of defining patterns only. In the older API, a formatter is used to both parse and format the date.

Rule of thumb, use DateTimeFormatter if you are using Java 8 new date and time API. For legacy codebase (Java 7 and below), use SimpleDateFormat for patterns.

3rd-Party Libraries

Now that we have developed a good understanding of performing string to date conversion using both new and old APIs included in core Java, let us look at some external libraries.

Joda-Time

Before Java 8, Joda-Time was developed to overcome the shortcomings of old date and time API. It provided an excellent alternative to core Java date and time classes and quickly became a de facto standard date and time library for Java before Java SE 8.

As of Java 8, all of its functionality is already implemented in the core Java in the form of the new date and time API. That is why the author of Joda-Time recommends users to migrate to Java 8 java.time (JSR-310) for working with dates and times.

In case if the migration is not possible, or if you are still using Java 7 or below, Joda-Time is still a great library to use.

To add Joda-Time to your Maven project, add the following dependency to pom.xml file:

<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.10.5</version>
</dependency>

For a Gradle project, include the below dependency to your build.gralde file:

implementation 'joda-time:joda-time:2.10.5'

Working with Joda-Time is very much similar to working with Java 8 new date and time API. Here is a quick example:

// date-time string
String str = "12/27/2019 14:15:45";

// define date and time pattern
DateTimeFormatter formatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
 
// convert string to date
DateTime dateTime = DateTime.parse(str, formatter);

The DateTime class from Joda-Time also supports the timezone information:

// date-time string
String str = "12/27/2019 14:15:45";

// define date and time pattern
DateTimeFormatter formatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
 
// convert string to date
DateTime dateTime = DateTime.parse(str, formatter);

// specify timezone
DateTime zonedDateTime  = dateTime.withZone(DateTimeZone.forID("Europe/Paris"));

Apache Commons Lang

The Apache Commons Lang library is another important 3rd-party library that provides many useful utility classes for working with legacy Date and Calendar classes.

To add the library to your Maven project, add the following dependency to pom.xml file:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.9</version>
</dependency>

For Gradle, add the below dependency to your build.gradle file:

implementation 'org.apache.commons:commons-lang3:3.9'

Now you can use the DateUtils class from Apache Commons Lang to parse a string into a Date object:

// date string
String str = "10-Jan-2020";

// parse string to date
Date date = DateUtils.parseDate(str, new String[] { "dd-MMM-yyyy", "dd/MM/yyyy" });

As you can see above, DateUtils.parseDate() accepts an array of patterns. It will parse each pattern after another. If no pattern matches the given input string, it throws a ParseException exception.

Common Date and Time Patterns

Let us take a look at some of the most common patterns that you can use with DateTimeFormatter and SimpleDateFormat for formatting and parsing dates and times:

LetterDescriptionExamples
yYear2019
MMonth in yearAugust, 08, 8
dDay in month1-31
EDay name in weekMonday, Friday
aAnte meridiem/Post meridiem markerAM, PM
HHour in day0-23
hHour in AM/PM1-12
mMinute in hour0-60
sSecond in minute0-60
SMillisecond in the minute978
zTimezonePacific Standard Time; PST; GMT-08:00
ZTimezone offset in hours (RFC pattern)-0800
XTimezone offset in ISO format-08; -0800; -08:00
sSecond in minute0-60

Look at this JavaDoc for a full list of symbols that you can use to define a date and time pattern for parsing a string into a date.

Summary

String to date conversion is one of the most frequent operations in Java. In this article, we have covered multiple ways to convert a string object into a date object including Java 8 new date and time API, legacy Date class, 3rd-party libraries like Joda-Time and Apache Commons Lang.

The new date and time API provides an extensive set of classes for parsing different types of strings into the newest API date and time objects. These classes are thread-safe, backward-compatible, and easier-to-use. You should always use the new API for parsing and formatting dates and times in Java 8 and higher.

If, for some reason, you cannot use the new API, go for the Joda-Time library. It is an excellent replacement of core Java date and time API before Java 8.

Read next: How to get current date and time in Java

✌️ Like this article? Follow @attacomsian on Twitter. You can also follow me on LinkedIn and DEV. Subscribe to RSS Feed.

👋 If you enjoy reading my articles and want to support me to continue creating free tutorials, Buy me a coffee (cost $5) .

Need help to launch a new product? I am available for contract work. Hire me to accomplish your business goals with engineering and design.