Explain Codes LogoExplain Codes Logo

Java string to date conversion

java
date-conversion
java-8
datetimeformatter
Alex KataevbyAlex Kataev·Nov 5, 2024
TLDR

Problem: Convert a String to a Date in Java with the old-school SimpleDateFormat. Match the date stamp, get the Date by calling parse():

String dateStr = "2023-04-01"; Date date = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);

Bottom line: Ensure the pattern in SimpleDateFormat matches your date's format.

Note: Although SimpleDateFormat is a classic, for Java 8 onwards, it's best to use the fresh and improved java.time package. It offers thread safety and an immutable design.

Java 8's solution with java.time

The magic of DateTimeFormatter

Java 8 brought to life the java.time API, simplifying date-time manipulations. To parse a date string like "January 2, 2010", harness the power of DateTimeFormatter:

// Comment from the future: "Hey, remember when we couldn't parse date strings directly? Good times..." DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH); LocalDate date = LocalDate.parse("January 2, 2010", formatter);

Use LocalDate for dates without times. LocalDateTime for date and time sans timezone. And ZonedDateTime for date and time with timezone information.

Common date patterns made easy!

For modern ISO 8601 formatted strings such as "2010-01-02", parsing is as easy as pie:

// ISO 8601, the only date standard to effortlessly travel through time (or code...) LocalDate date = LocalDate.parse("2010-01-02");

The java.time API respects ISO 8601 and uses it as its default format. Gotta represent custom patterns? Simply define a DateTimeFormatter with your specific format.

Timestamp madness, busted

Needing to obtain a timestamp from a LocalDate? Convert to Instant and get that epoch millisecond value:

// Who needs a time machine when you've got timestamps? long timestamp = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();

Gem points to know

Thread safety (Life saver!)

The classic SimpleDateFormat is not thread-safe. That means potential bugs crawling in multi-threaded environments. Always spawn new instances within the method scope or switch to java.time API, which offers thread-safe date-time classes.

Stay in your Locale

The Locale decides how textual date representations are unraveled. Always specify the locale to skip subtle bugs and ParseExceptions. Working with English-language dates? Go for Locale.ENGLISH.

Solid as a rock and safe as a locker

java.time classes, like LocalDate and LocalDateTime, are immutable and thread-safe. They come with handy methods to get the year, month, and day. Methods like getYear(), getMonthValue(), getDayOfMonth(), and others are your best friends.

Skip the oldies

Avoid using java.util.Date and java.util.Calendar. They are outdated and not thread-safe. Plus, they're yesterday's news. Embrace the new java.time API, inspired by Joda-Time, for a simplified coding life.

Strategies for custom date patterns and legacy dilemmas

Tame the wild, custom patterns

Got dates with a rare format? Define a DateTimeFormatter:

// Because 'E, MMM d yyyy' is totally readable... said no human ever DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("E, MMM d yyyy"); LocalDate customDate = LocalDate.parse("Tue, Apr 1 2023", customFormatter);

Modernising legacy code

Got an old codebase with SimpleDateFormat? Time to turn to java.time. If not feasible, ensure each SimpleDateFormat instance is confined to the method to prevent concurrency chaos.

Parsing with time zones. Yes, it's a thing!

Parse dates with time zone info using ZonedDateTime:

// When you need to know the exact second everywhere on Earth... DateTimeFormatter withTimeZone = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); ZonedDateTime dateTimeWithZone = ZonedDateTime.parse("2023-04-01 12:00:00 UTC", withTimeZone);

Prepare for edge cases

Beware the Daylight Saving Time and leap seconds

Always examine how your date-time code behaves around Daylight Saving Time transitions and when dealing with leap seconds. The java.time API has got you covered.

Date normalisation

Parsing incomplete dates? Note that java.time.LocalDate defaults to the day's start in absence of specific time info.

Milliseconds since, well... FOREVER (epoch)

For applications needing a dance with millisecond values since the Unix epoch, convert LocalDate or LocalDateTime to Instant first:

// The exact moment since... dinosaurs? Nah, just Unix epoch. long millisecondsSinceEpoch = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();