# How to convert a string to date in Java

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Dec 22, 2019, updated Oct 14, 2022. Topics: Java.
Canonical URL: https://attacomsian.com/blog/java-convert-string-to-date

> Learn how to convert a string to a date using Java 8 new date and time API, legacy Date class, and external libraries.

In this tutorial, you'll learn 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](https://attacomsian.com/blog/java-new-date-time-api) to perform the string-to-date conversion. 

Afterward,  we'll look at the legacy `java.util.Date` class 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 the `java.time.*` package) to make it easy to work with dates in Java. These classes use [ISO-8601 format](https://en.wikipedia.org/wiki/ISO_8601) 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`](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_LOCAL_DATE) format to parse the string into a date:

```java
parse(CharSequence text)
```

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

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

```java
parse(CharSequence text, DateTimeFormatter formatter)
```

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

### Convert a string to `LocalDate` object

The `LocalDate` class **represents a date in ISO-8601 format** (yyyy-MM-dd) without any time information. It differs from the old `Date` and doesn't store time or timezone information. 

Unlike `Date`, `LocalDate` provides utility methods to parse and format dates and 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:

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

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

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

```java
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:

```java
// 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`:

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

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

### Convert a string to `LocalTime` object

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

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

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

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

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

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

```java
// 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 a string to `LocalDateTime` object

The `LocalDateTime` 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](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_LOCAL_DATE_TIME) (yyyy-MM-ddTHH:mm).

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

```java
// 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`:

```java
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`:

```java
// 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 a string to `ZonedDateTime` object

The `ZonedDateTime` class handles 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:

```java
// 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 a string to `OffsetDateTime` object

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`:

```java
// 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:

```java
// 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 a string to `Instant` object

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](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_INSTANT) format (e.g. *2011-12-03T10:15:30Z*).

Here is an example:

```java
// 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`:

```java
// 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:

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

> Look at [Introduction to Java 8 Date and Time API](https://attacomsian.com/blog/java-new-date-time-api) guide for more new date and time API examples.

## Convert a string to `java.util.Date`

Before Java 8, both `java.util.Date` and `java.util.Calendar` classes were used to handle dates and times. To convert a string into an instance of `Date`, you need to use the `SimpleDateFormat` to define a custom date and time pattern. 

Here are a few examples:

```java
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:

```bash
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, you can not 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`:

```java
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:

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

## `DateTimeFormatter` vs. `SimpleDateFormat`

After learning string-to-date conversion through Java 8 new date and time APIs `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](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) 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:

```java
// `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 clear. In the new date and time API, the classes have their **own parse and format methods** and use `DateTimeFormatter` for patterns only. In the older API, a **formatter is used to both parse and format** the date.

Rule of thumb, use `DateTimeFormatter` if you use 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 new and old APIs included in core Java, let us look at some external libraries. 

### Joda-Time

Before Java 8, [Joda-Time](https://www.joda.org/joda-time/) was developed to overcome the shortcomings of the 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.

Since Java 8, all Java-Time 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 migrate to Java 8 `java.time` (JSR-310) for working with dates and times.

If the migration is **not** possible, or if you are using **Java 7** or below, Joda-Time is still a good library to handle date and time.

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

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

For a [Gradle project](https://attacomsian.com/blog/install-gradle-on-ubuntu), include the below dependency to your `build.gradle` file:

```groovy
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:

```java
// 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:

```java
// 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](https://commons.apache.org/proper/commons-lang/) library is another 3rd-party library that provides many utility classes for working with legacy `Date` and `Calendar` classes.

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

```xml
<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:

```groovy
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:

```java
// 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:

| Letter | Description | Examples |
| -------- | -------- | -------- |
| `y` | Year | 2019 |
| `M` | Month in year | August, 08, 8 |
| `d` | Day in month | 1-31 |
| `E` | Day name in week | Monday, Friday |
| `a` | Ante meridiem/Post meridiem marker | AM, PM |
| `H` | Hour in day | 0-23 |
| `h` | Hour in AM/PM | 1-12 |
| `m` | Minute in hour | 0-60 |
| `s` | Second in minute | 0-60 |
| `S` | Millisecond in the minute | 978 |
| `z` | Timezone | Pacific Standard Time; PST; GMT-08:00 |
| `Z` | Timezone offset in hours (RFC pattern) | -0800 |
| `X` | Timezone offset in ISO format | -08; -0800; -08:00 |
| `s` | Second in minute | 0-60 |

Look at this [JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns) for the complete 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 covered multiple ways to convert a string object into a date object, including Java 8 new date and time API, legacy `Date` class, and 3rd-party libraries like Joda-Time and Apache Commons Lang. 

The [new date and time API](https://attacomsian.com/blog/java-new-date-time-api) provides a comprehensive set of classes for parsing different types of strings into the 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 for core Java date and time API before Java 8.

**Read next:** [How to get current date and time in Java](https://attacomsian.com/blog/java-get-current-date-time)
