Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Converting date to epoch value produces false output

I am trying to convert the below date time string object into a unix epoch timestamp value. However, when i run the program i notice that it generates an epoch value of 1404461110000 which when i check on my ubuntu unix machine is Wed Aug 7 18:06:40 However in reality i am passing July 04 2014-07-04 04:05:10. I have a time zone of America/Toronto on my ubuntu machine but I don't think it should matter here ?

Java code:

            long epoch = 0;
            String str = "2014-07-04 04:05:10";   // UTC

            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date datenew = df.parse(str);
            epoch = datenew.getTime();

            System.out.println(epoch); // prints 1404461110000

Ubuntu Linux 14.04

date -d@1404461110000

displays= Wed Aug 7 18:06:40 EDT 46475

like image 961
user3846091 Avatar asked Apr 28 '26 10:04

user3846091


2 Answers

The issue is that you're not dealing with a unix timestamp when calling getTime() in Java. Unix timestamps are expressed in seconds since the epoch, while the values you're getting from Java are milliseconds since the epoch (Jan 01 1970), hence the difference.

It would have to be:

epoch = datenew.getTime() / 1000;

This should get you at least a couple of 10000 years closer. If you still see a difference after that, it's timezone-related, and can be accommodated for by specifying the timezone on your DateFormat instance.

like image 145
Robby Cornelissen Avatar answered May 01 '26 00:05

Robby Cornelissen


java.time

The legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat etc.) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

Solution using java.time, the modern API:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        String str = "2014-07-04 04:05:10"; // UTC

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse(str, dtf);
        ZonedDateTime zdtUtc = ldt.atZone(ZoneId.of("Etc/UTC"));
        Instant instant = zdtUtc.toInstant();
        long epochMillis = instant.toEpochMilli();
        long epochSeconds = TimeUnit.SECONDS.convert(epochMillis, TimeUnit.MILLISECONDS);
        System.out.println(epochSeconds);

        // Corresponding date-time in America/Toronto
        ZonedDateTime zdtToronto = instant.atZone(ZoneId.of("America/Toronto"));
        System.out.println(zdtToronto);
    }
}

Output:

1404446710
2014-07-04T00:05:10-04:00[America/Toronto]

Learn more about java.time, the modern date-time API* from Trail: Date Time.

Some important notes:

  1. Unix time specifies seconds since the Epoch.
  2. We should avoid performing calculations ourselves if there is an OOTB (Out-Of-The-Box) API available for it e.g. TimeUnit#convert.

* 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.

like image 35
Arvind Kumar Avinash Avatar answered Apr 30 '26 22:04

Arvind Kumar Avinash