Reputation: 13
I'm parsing a timestamp which is "2022-01-12T17:17:34.512492+0000", this format is "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'ZZZZ" (ISO8601).
I want to convert it in epoch unix time, I'm using java.text.SimpleDateFormat. I tried two methods but both don't work:
1- First Method
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'ZZZZ'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
Error showed:
java.text.ParseException: Unparseable date: "2022-01-12T17:17:34.512492+0000"
2- This second Method shows an output but is incorrect
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+0000'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
println(epoch)
Output:
1642004766492
If you convert this epoch to HUMAN DATE: "Wednesday, 12 January 2022 16:26:06.492"
The hours,minutes and seconds are wrong.
Upvotes: 1
Views: 696
Reputation: 2638
SimpleDateFormat
is outdated, as Gael pointed out.
The Time API now supports up to nanoseconds, so microseconds are not an issue here. You should use DateTimeFormatter with ZonedDateTime
. Your pattern is slightly wrong. Checking the docs for Offset Z
:
Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.
You can also print the time using toInstant
to make sure it was parsed correctly:
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
val parsed = "2022-01-12T17:17:34.512492+0000"
val p = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZ"
val dtf = DateTimeFormatter.ofPattern(p)
val zdt = ZonedDateTime.parse(parsed, dtf)
println(zdt.toInstant) // 2022-01-12T17:17:34.512492Z
println(zdt.toInstant.toEpochMilli) // 1642004254512
Here is a nice article that explains in detail converting an ISO 8601 in Java. The comments at the end are particularly useful, as it shows the difference between the different patterns used.
Upvotes: 2
Reputation: 281
The timestamp you have has microseconds precision. Such precision is not supported by SimpleDateFormat
. Also, Unix epoch time is usually up to milliseconds precision.
Possible solution here is to explicitly round the microseconds to milliseconds in the string before parsing, then use the yyyy-MM-dd'T'HH:mm:ss.SSSZ
format.
String parsed = "2022-01-12T17:17:34.512492+0000";
String upToSeconds = parsed.substring(0, "yyyy-MM-ddTHH:mm:ss".length());
String microseconds = parsed.substring("yyyy-MM-ddTHH:mm:ss.".length(), "yyyy-MM-ddTHH:mm:ss.".length() + "SSSSSS".length());
String timezone = parsed.substring("yyyy-MM-ddTHH:mm:ss.SSSSSS".length());
String roundedMilliseconds = new BigDecimal(microseconds).divide(new BigDecimal("1000"), 0, RoundingMode.HALF_UP).toString();
String reformatted = upToSeconds + "." + roundedMilliseconds + timezone;
System.out.println(reformatted); // 2022-01-12T17:17:34.512+0000
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
long epoch = sdf.parse(reformatted).getTime();
System.out.println(epoch); // 1642007854512
System.out.println(Instant.ofEpochMilli(epoch)); // 2022-01-12T17:17:34.512Z
Upvotes: 0
Reputation: 21
looks like epoch has data in internal datetime format. and you should convert it to string format like this in java
public static String dateToString(Date d, String string_format) {
String result = "";
if(d != null) {
result = new SimpleDateFormat(string_format).format(d);
}
return result;
}
Upvotes: 0