perplexedDev
perplexedDev

Reputation: 835

Convert a timestamp to ISO format date string

I have a logic in python that I am converting into Java code. The logic is I need to read from a timestamp attribute in JSON file and convert it into ISO date format. Python query:

datetime.datetime.fromtimestamp(jsonMsg["time"]).isoformat(timespec='seconds')

Here is the code I wrote in Java 1627065646.444 is an example of the value I get from JSON script

long timestamp = (long) 1627065646.444 * 1000;
        Timestamp time = new Timestamp(timestamp);
        Date d = new Date(time.getTime());

        DateFormat df = new SimpleDateFormat();
        String dateToString = df.format(d);
        
        LocalDateTime datetime = LocalDateTime.parse(dateToString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        ZoneOffset offset = ZoneOffset.UTC;
        String formattedTimeStamp = datetime.atOffset(offset).toString();

When I run the code I get compile error "Text '7/23/21 11:40 AM' could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0" This exception occurs at LocalDateTime.parse(dateToString, DateTimeFormatter.ISO_LOCAL_DATE_TIME. Can someone please help me in understanding what I am doing wrong here.

Upvotes: 0

Views: 3042

Answers (1)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79580

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        long timestamp = (long) (1627065646.444 * 1000);

        Instant instant = Instant.ofEpochMilli(timestamp);
        System.out.println(instant);

        ZonedDateTime zdt = instant.atZone(ZoneOffset.UTC);
        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(ldt);

        // A custom format
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("M/d/u h:m:s a", Locale.ENGLISH);
        String formatted = dtf.format(zdt);
        System.out.println(formatted);
    }
}

Output:

2021-07-23T18:40:46.444Z
2021-07-23T18:40:46.444
7/23/2021 6:40:46 PM

ONLINE DEMO

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Learn more about the modern Date-Time API* from Trail: Date Time.

Apart from this, what else is wrong with your code?

You have done

long timestamp = (long) 1627065646.444 * 1000;

in which 1627065646.444 will be cast to long resulting in 1627065646 and thus the result of the multiplication will be 1627065646000, not 1627065646444 what you are expecting. You need to cast to long after performing the multiplication.

A valuable comment by Ole V.V.:

I’d use Math.round(1627065646.444 * 1000) to make sure that floating-point inaccuracy is handled.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Upvotes: 3

Related Questions