Java Converting date to epoch value creates spurious output
I am trying to convert a date string object below date to a unix epoch timestamp value. However, when I run the program, I notice that it generates an epoch value 1404461110000, which when I check my Ubuntu unix machine is Wed Aug 7 18:06:40 However, I actually go through 04 Jul 2014-07- 04 04: 05.10. I have America / Toronto timezone on my ubuntu machine, but I don't think it should make a difference 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
display = Wed Aug 7 18:06:40 EDT 46475
source to share
The problem is that you don't have a unix timestamp when called getTime()
in Java. Unix timestamps are in seconds since epoch, and the values you get from Java are milliseconds since epoch (Jan 1, 1970) is therefore the difference.
It should be:
epoch = datenew.getTime() / 1000;
This should get you at least a couple of 10,000 years closer. If you still see a difference after doing this, it is time zone related and can be accounted for by specifying the time zone on your instance DateFormat
.
source to share
You need to tell Java that the timestamp is UTC, not just add a comment about it.
long epoch = 0;
String str = "2014-07-04 04:05:10"; // UTC
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC")); // assume UTC
Date datenew = df.parse(str);
epoch = datenew.getTime();
System.out.println(epoch);
source to share
Joda time
FYI, here's the same code, but done in Joda-Time 2.4. The new java.time package in Java 8 (inspired by Joda-Time) can be used in a similar way.
The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use one of the two libraries mentioned above.
Sample code
Your input string is close to ISO 8601 standard , but not quite, missing T
in the middle and offset from UTC . Joda-Time has a built-in formatter for parsing / generating in ISO 8601. So instead of defining our own formatting, modify the input string slightly by inserting T
.
String inputRaw = "2014-07-04 04:05:10"; // UTC
String input = inputRaw.replace( " ", "T" ); // Convert to standard ISO 8601 format.
We then tell the DateTime constructor to parse the string in UTC (zero offset). Unlike java.util.Date, DateTime knows its own assigned time zone.
DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );
Easily configurable for time in Toronto, for fun, or for debugging / sanity testing.
DateTime dateTimeToronto = dateTimeUtc.withZone( DateTimeZone.forID( "America/Toronto" ) );
Like java.util.Date, Joda-Time internally tracks time as the number of milliseconds from the Unix era (early 1970) to UNIVERSAL GLOBAL TIME. This means using 64-bit long
, not regular 32-bit int
. (By the way, java.time tracks nanoseconds .) So, if we want seconds-since-unix-epochs, divide them by a thousand.
long millisecondsSinceEpoch = dateTimeUtc.getMillis(); // Use a "long", not "int".
long secondsSinceEpoch = ( millisecondsSinceEpoch / 1000L );
Dump for console.
System.out.println( "input: " + input );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeToronto: " + dateTimeToronto );
System.out.println( "millisecondsSinceEpoch: " + millisecondsSinceEpoch );
System.out.println( "secondsSinceEpoch: " + secondsSinceEpoch );
At startup.
input: 2014-07-04T04:05:10 dateTimeUtc: 2014-07-04T04:05:10.000Z dateTimeToronto: 2014-07-04T00:05:10.000-04:00 millisecondsSinceEpoch: 1404446710000 secondsSinceEpoch: 1404446710
source to share