Question

How to Convert a String to a Date in Java

javastringdatetimedata-conversion

Question

How can I convert a String in the format "January 2, 2010" into a date in Java?

My end goal is to extract the month, day, and year as integers and convert the date into a time value. For example, I was considering code like this:

Date date = new Date();
date.setMonth(...);
date.setYear(...);
date.setDay(...);
long currentTime = date.getTime();

What is the best approach for parsing this kind of date string in Java?

Short Answer

By the end of this page, you will understand how to parse a human-readable date string such as "January 2, 2010" in Java, why manually setting fields on Date is not the best approach, and how to use the modern Java date-time API to safely extract year, month, and day or convert the result to a timestamp when needed.

Concept

Java date parsing means converting text like "January 2, 2010" into a structured date object that Java can understand.

The key idea is that a date string is just text until you tell Java what pattern it follows. In this case:

  • January is the full month name
  • 2 is the day of the month
  • 2010 is the year

So Java needs a formatter pattern that matches that shape.

In older Java code, developers often used java.util.Date and SimpleDateFormat. That works, but modern Java prefers the java.time package introduced in Java 8.

Why this matters:

  • Parsing lets your program accept user input or file data.
  • Structured date objects are safer than manually splitting strings.
  • Modern APIs avoid many bugs found in older Date methods.

Important note: methods like Date#setMonth(), Date#setYear(), and similar older setters are considered outdated and confusing. They have odd behavior, such as zero-based months and year offsets in some cases. In real Java code, you should usually parse into LocalDate first, then convert only if needed.

Mental Model

Think of a date formatter like a reading template.

If someone gives you the text "January 2, 2010", you need instructions that say:

  • first read a full month name
  • then read a day number
  • then read a 4-digit year

Without that template, Java just sees a plain string.

A good mental model is:

  • String = raw label on a box
  • Date/LocalDate = the actual organized contents
  • Formatter = the instructions for opening and arranging the contents correctly

So you do not manually build the date piece by piece unless you really need to. Usually, you let the formatter read the whole string for you.

Take Quiz

Syntax and Examples

The modern Java approach uses LocalDate and DateTimeFormatter.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String input = "January 2, 2010";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
        LocalDate date = LocalDate.parse(input, formatter);

        int month = date.getMonthValue();
        int day = date.getDayOfMonth();
        int year = date.getYear();

        System.out.println(date);   // 2010-01-02
        System.out.println(month);  // 1
        System.out.println(day);    // 2
        System.out.println(year);   // 2010
    }
}

Pattern explanation:

  • MMMM = full month name like January
  • d = day of month like 2
  • yyyy = 4-digit year

If you must work with the older Date class, you can still parse the string:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        String input = "January 2, 2010";

        SimpleDateFormat formatter = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
        Date date = formatter.parse(input);

        long time = date.getTime();
        System.out.println(date);
        System.out.println(time);
    }
}

This older version works, but LocalDate is the preferred choice for a date without a time.

Step by Step Execution

Consider this example:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String input = "January 2, 2010";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
        LocalDate date = LocalDate.parse(input, formatter);

        System.out.println(date.getYear());
        System.out.println(date.getMonthValue());
        System.out.println(date.getDayOfMonth());
    }
}

What happens step by step:

  1. input stores the raw text: "January 2, 2010".
  2. DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH) creates parsing rules.
    • MMMM expects a full month name.
    • d expects the day number.
    • yyyy expects the year.
  3. LocalDate.parse(input, formatter) reads the string using those rules.
  4. Java creates a LocalDate representing January 2, 2010.
  5. date.getYear() returns 2010.
  6. date.getMonthValue() returns 1.
  7. date.getDayOfMonth() returns 2.

If you later need a timestamp, you must add a time and time zone because LocalDate only represents a calendar date, not a moment in time.

Example:

import java.time.LocalDate;
import java.time.ZoneId;

LocalDate date = LocalDate.of(2010, 1, 2);
long timestamp = date.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();

This means: take the date, use the start of the day in a specific time zone, then convert it to milliseconds since the Unix epoch.

Real World Use Cases

Date parsing is common in many kinds of Java programs:

  • Web forms: a user enters a date like January 2, 2010
  • CSV imports: a file contains date columns as text
  • APIs: incoming JSON or query parameters contain dates as strings
  • Reports: analytics tools convert text dates into sortable values
  • Scheduling systems: appointments or deadlines start as human-readable strings

Examples:

  • A payroll app parses employee start dates.
  • A booking system parses check-in dates.
  • A log processing script turns text dates into timestamps.
  • A REST API validates and stores a birth date sent as a string.
Take Quiz

Real Codebase Usage

In real projects, developers usually avoid manually calling old Date setter methods. Instead, they follow safer patterns.

Common patterns include:

  • Parse once, use many times: convert the input string into a LocalDate immediately.
  • Validation: reject invalid date strings early.
  • Guard clauses: return an error if parsing fails.
  • Conversion only at boundaries: use Date or timestamps only when interacting with legacy libraries or databases.
  • Locale-aware parsing: specify Locale.ENGLISH when month names are written in English.

Example with validation:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;

public class DateParser {
    private static final DateTimeFormatter FORMATTER =
        DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);

    public static LocalDate parseDate(String input) {
        if (input == null || input.isBlank()) {
            throw new IllegalArgumentException("Date string cannot be empty");
        }

        try {
            return LocalDate.parse(input, FORMATTER);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid date format. Expected example: January 2, 2010", e);
        }
    }
}

This style is common because it keeps parsing logic in one place and makes errors easier to handle.

Common Mistakes

Beginners often run into these problems when working with dates in Java.

1. Using old Date setter methods

Broken approach:

Date date = new Date();
date.setMonth(1);
date.setYear(2010);

Why it is a problem:

  • Old Date setters are deprecated in practice.
  • They are confusing and easy to misuse.
  • Some values are offset or zero-based.

Better approach:

LocalDate date = LocalDate.of(2010, 1, 2);

2. Forgetting the locale for month names

Broken code:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy");

Why it can fail:

  • January is an English month name.
  • If the system default locale is not English, parsing may fail.

Better:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);

3. Using the wrong pattern letters

Broken code:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM d, yyyy", Locale.ENGLISH);

Why it is wrong:

  • MM expects a numeric month like 01
  • MMMM expects a full month name like January

Correct:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);

4. Assuming a date automatically includes a time

A LocalDate has no hour, minute, second, or time zone.

If you need milliseconds since epoch, you must specify a time and zone:

long millis = date.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();

5. Mixing up day of month and day of week

Broken idea:

date.getDay();

With older APIs, this may not mean what you expect. Use clear modern methods:

date.getDayOfMonth();

Comparisons

Here is a comparison of common Java date options:

ApproachBest forGood pointsDrawbacks
LocalDateA date without a timeClear, modern, safe APINeeds extra conversion for timestamps
LocalDateTimeDate and time without time zoneUseful for local schedulesNot a specific instant in time
ZonedDateTimeDate and time with time zoneGood for real-world timestampsSlightly more complex
java.util.DateLegacy code compatibilityStill found in older librariesOld API, confusing setters
SimpleDateFormatLegacy string parsingWorks in old codebasesOld API, less safe, mutable

LocalDate vs Date

FeatureLocalDateDate
Represents only a calendar dateYesNo
Modern Java APIYesNo
Easy field accessYesLess clear
Good for new codeYesUsually no
Timestamp support built inNo, needs conversionYes

Rule of thumb:

  • Use LocalDate for dates like birthdays, due dates, and calendar entries.
  • Use timestamps or Instant when you need an exact moment in time.
  • Use Date only when dealing with old APIs.
Take Quiz

Cheat Sheet

// Parse "January 2, 2010"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse("January 2, 2010", formatter);

Pattern letters:

  • MMMM = full month name (January)
  • MMM = short month name (Jan)
  • d = day of month (2)
  • dd = day of month with leading zero (02)
  • yyyy = 4-digit year (2010)

Extract values:

int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();

Convert to timestamp in milliseconds:

long millis = date.atStartOfDay(ZoneId.systemDefault())
                  .toInstant()
                  .toEpochMilli();

Legacy parsing:

SimpleDateFormat formatter = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = formatter.parse("January 2, 2010");
long millis = date.getTime();

Rules to remember:

  • Prefer java.time over old Date APIs.
  • Use Locale.ENGLISH when parsing English month names.
  • LocalDate has no time zone.
  • Do not use old Date#setMonth() and Date#setYear() in new code.

FAQ

How do I parse January 2, 2010 in Java?

Use LocalDate.parse() with a DateTimeFormatter pattern of "MMMM d, yyyy" and Locale.ENGLISH.

Should I use Date or LocalDate in Java?

For new code, use LocalDate if you only need a calendar date. Use Date only for legacy compatibility.

Why does Java need Locale.ENGLISH here?

Because January is an English month name. Without the correct locale, parsing may fail on systems using another language.

How do I get the month, day, and year as integers?

Use:

int month = date.getMonthValue();
int day = date.getDayOfMonth();
int year = date.getYear();

How do I convert a parsed date to milliseconds?

If you have a LocalDate, convert it to the start of the day in a time zone, then get epoch milliseconds.

What is wrong with Date#setMonth() and Date#setYear()?

They belong to the old date API and are confusing, easy to misuse, and not recommended for modern Java code.

Can I still use SimpleDateFormat?

Yes, especially in older codebases, but for new development java.time is the better choice.

Take Quiz

Mini Project

Description

Build a small Java utility that reads date strings like "January 2, 2010", parses them into LocalDate, prints the year, month, and day, and then converts the date to epoch milliseconds at the start of the day. This demonstrates the full workflow of parsing, extracting fields, and converting to a machine-friendly time value.

Goal

Create a reusable Java program that safely parses a human-readable date string and converts it into structured values and a timestamp.

Requirements

  • Accept a date string in the format Month day, year
  • Parse the string using the correct formatter pattern
  • Print the extracted year, month, and day as integers
  • Convert the parsed date to epoch milliseconds
  • Handle invalid input with a clear error message
Take Quiz

Keep learning

Related questions

View more