简体   繁体   中英

Java 8 best way to parse text date to millisecond timestamp

I want to create a Java class with thread-safe static methods to parse dates. I understand that some of the Java 7 (and earlier) date time classes are not thread-safe. What is the best thread-safe implementation in Java 8 of this functionality:

String text = "5/16/2008";
long timestamp = DateUtil.getTimestamp(text);

In Java 7 and earlier, you would do this:

public class DateUtil {

    public static long getTimestamp(String text) {
        DateFormat df = new SimpleDateFormat("M/d/yyyy");
        df.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        long timestamp = df.parse(text).getTime();
        return timestamp;
    }

}

But instead of creating a new instance of DateFormat for every call, I want to share a single static instance for all calls to this static getTimestamp method. My understanding is that this is not thread-safe.

One key requirement is that the text I want to parse has a short date like "5/16/2008" without HH:mm:ss resolution.

I also don't want to use a third party library like Joda-Time, but rather only standard Java 8 classes.

Here's a version of your code refactored to use the java.time.* package in Java 8. It uses a static final formatter instance, which is thread-safe and immutable, unlike java.text.SimpleDateFormat .

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class DateUtil {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");

    public static long getTimestamp(String text) {
        LocalDate localDate = LocalDate.parse(text, formatter);
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()).getTime();
    }
}

You can use joda-time lib. DateTime is immutable - and once created the values do not change, so class can safely be passed around and used in multiple threads without synchronization.
A companion mutable class to DateTime is MutableDateTime , of which the class can be modified and are not thread-safe.

DateTimeFormatter formatter = DateTimeFormat.forPattern("M/d/yyyy'T'HH:mm:ss.SSSZZ")
    .withLocale(Locale.ROOT).withChronology(ISOChronology.getInstanceUTC());
DateTime dt = formatter.parseDateTime(text);

Reference of DateTimeFormatt : DatetimeFormat api .

As stated in ck1's answer, usage of java.time API is a better approach than the legacy classes. DateTimeFormatter is immutable and thread-safe, and using a static final instance of it will solve your problem. The only part where I differ from that answer is in the code , where the Date class is used to get the time. I would like to take the java.time approach here as well. Below is my version :

public class DateUtil {

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");

    public static long getTimestamp(String text) {
        LocalDate localDate = LocalDate.parse(text, formatter);
        return Instant.from(localDate.atStartOfDay(ZoneId.systemDefault())).toEpochMilli();
    }

    public static void main(String[] args) {
        String text = "5/16/2008";
        long timestamp = DateUtil.getTimestamp(text);
        System.out.println(timestamp);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM