First don’t store your datetime as a string in PostgreSQL and don’t retrieve a string like the one you are showing from the database. Store a proper date/time type; in your case probably timestamp with time zone
. And instead of retrieving a string, fetch a corresponding Java datetime type. For example:
PreparedStatement select = yourDatabaseConnection
.prepareStatement("select ts from your_table where id = 4;");
ResultSet rs = select.executeQuery();
if (rs.next()) {
OffsetDateTime dateTime = rs.getObject("ts", OffsetDateTime.class);
long milliseconds = dateTime.toInstant().toEpochMilli();
// Do something with milliseconds
}
(I have not tested this snippet since I haven’t got PostgreSQL installed.)
If for one reason or another you cannot avoid getting the string:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSx");
String stringFromDatabase = "2019-04-04 12:24:53.754787+00";
OffsetDateTime dateTime
= OffsetDateTime.parse(stringFromDatabase, formatter);
long milliseconds = dateTime.toInstant().toEpochMilli();
System.out.println(milliseconds);
This snippet I have tried running. The output is:
1554380693754
Since PostgreSQL stores microsecond precision and millisconds since the epoch obviously don’t, we have lost the three last decimals of the original value.
I am using and recommending java.time, the modern Java date and time API. The datetime classes that you tried to use — SimpleDateFormat
and Date
— are long outdated and were always poorly designed. So avoid those.
What went wrong in your code?
- Others have already pointed out that for parsing your string you need uppercase
HH
for hour of day from 00 through 23. Lowercase hh
is for hour within AM or PM from 01 through 12. Since 12 AM means 00, parsing an hour of 12 gives the wrong result that you have observed, while other hour values work.
- The single
M
, on the other hand, doesn’t matter in this case, it works the same for parsing as MM
(for formatting we need MM
if we want two digits always, as in your example string).
- You neither parsed the fraction of second nor the UTC offset of
+00
. If you got an approximately correct result in spite of this, you’ve been struck by luck and should not count on this being the case on other computers or JVMs with other default settings.
Links