Java/Convert Iso-8601 (2010-12-16T13:33:50.513852Z) to Date Object

Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java

Try with this pattern (note the X at the end and the 'T' in the middle):

"yyyy-MM-dd'T'HH:mm:ss.SSSX"

From Java's SimpleDateFormat's documentation:

ISO 8601 Time zone:

...

For parsing, "Z" is parsed as the UTC time zone designator.

And, from the part where it describes the different characters:

X - Time zone - ISO 8601 time zone

EDIT

If using Android, then "X" is not supported.

You can use this pattern (note Z is a literal now):

"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

But then you'll get the date on your current timezone and would need to convert it to UTC if needed.

Formatter in DateTimeFormatter for ISO 8601 date format of the time

Depending on your situation you may not need to specify a formatter at all. The classes of java.time parse (and print) ISO 8601 format as their default, that is, without any explicit formatter. As the description in your image says, this is the format you’ve got.

However two of the predefined formatters that you are linking to do match your example:

  1. ISO_INSTANT
  2. ISO_OFFSET_DATE_TIME

Which one to use depends on any requirements for the type you want to parse the string into. It’s simplest to parse into an Instant. Don’t specify a formatter, just use Instant.parse:

    String swapiCreatedString = "2014-12-09T13:50:51.644000Z";
Instant created = Instant.parse(swapiCreatedString);
System.out.println("Created " + created);

Output:

Created 2014-12-09T13:50:51.644Z

I you need to manipulate the parsed datetime further, for example format it for a user, OffsetDateTime offers more possibilities:

    OffsetDateTime created = OffsetDateTime.parse(swapiCreatedString);

Again no formatter is needed for parsing. Output is identical to the above.

I guess that the reasons why you didn’t see that the two mentioned formatters match include:

  • None of the examples include fraction of second, but the formatters accept between 0 and 9 decimals (inclusive) of fraction of second.
  • The example offset date-time has offset +01:00. You couldn’t know that Z works as an offset too. It’s pronounced “Zulu” and denotes UTC.

To answer your question more directly: None of your formats are quite correct. Since as I said Z is an offset, you will want to parse it as such and not as a literal so you get the offset information from the string. Without it you wouldn’t know at which offset to interpret the 13:50:51.644. .SSSSSS is correct for fraction of second while .nnnnnn means nanosecond of second and is incorrect here. There are 10^9 nanoseconds in a second, so n only works if there are 9 digits of nanoseconds. Maybe your own example gives the best illustration:

    // nnnnnn is incorrect
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.nnnnnn'Z'");
String swapiCreatedString = "2014-12-09T13:50:51.644000Z";
LocalDateTime created = LocalDateTime.parse(swapiCreatedString, formatter);
System.out.println("Created " + created);

Created 2014-12-09T13:50:51.000644

You see that the 51.644 seconds have been incorrectly changed to 51.000644.

parse String to 'yyyy-mm-ddThh:mm:ss.SSSZ' ISODate java

Your code is not working since Z is a reserved character used to interpret RFC-822 time zones :

RFC 822 time zone: For formatting, the RFC 822 4-digit time zone format is used:

 RFC822TimeZone:
Sign TwoDigitHours Minutes
TwoDigitHours:
Digit Digit

Since Java 7, you can use X to interpret ISO-8601 time zones https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html . The following works :

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");

However, on my computer,

System.out.println(newDateString);

results in the following output :

2017-02-17T05:23:17.452+01

Alternatively, if you are sure to have only UTC dates, you could escape the Z letter with simple quotes :

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

And here is the displayed result :

2017-02-17T04:23:17.452Z

Parse Date Format

i think you have got the 2nd argument of your to_date function wrong which is causing null values in your output

the +530 in your timestamp is the Zulu value which just denotes how many hours and mins ahead (for +) or behind (for -) the current timestamp is withrespect to UTC.
Please refer to the response by Basil here Java / convert ISO-8601 (2010-12-16T13:33:50.513852Z) to Date object This link has full details available for the same.

To answer your question if you replace +0530 by Z it should solve your problem.

Here is the spark code in scala that I tried and worked:

val data = Seq("20201021T00:00:00+0530",
"20211011T00:00:00+0530",
"20200212T00:00:00+0300",
"20211021T00:00:00+0530",
"20211021T00:00:00+0900",
"20211021T00:00:00-0500")

import spark.implicits._
val sparkDF = data.toDF("custom_time")

import org.apache.spark.sql.functions._
val spark_DF2 = sparkDF.withColumn("new_timestamp", to_date($"custom_time", "yyyyMMdd'T'HH:mm:ssZ"))

spark_DF2.show(false)

here is the snapshot of the output. As you can see there are no null values.
output

Date Conversion from string to java.util.Date and then to java.sql.Date

Using SimpleDateFormatter you can achieve this.

 SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String dateInString = "2014-05-26T00:00:00Z";

try {

Date utilDate = formatter.parse(dateInString.replaceAll("Z$", "+0000"));
System.out.println(utilDate);

} catch (ParseException e) {

}

After getting you java.util.Date object you can convert it into java.sql.Date using follow way,

java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());

For more similar type of conversions of string into Date. see this

SimpleDateFormat not parsing time correctly

This is one of the problems with the obsolete Date, Calendar and SimpleDateFormat classes. You shouldn't use it, for it's supplanted by the new Date and Time API in Java 8. It is available in the java.time package.

String str = "2018-11-01T18:07:55.6725292Z";
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'";

LocalDateTime ts = LocalDateTime.parse(str, DateTimeFormatter.ofPattern(pattern));
System.out.println("Text 2018-11-01T18:07:55.6725292Z parses as " + ts);

It seems that SimpleDateFormat is only able to read up to three millisecond digits. The parsing process works if one truncates the fraction portion of the date to three digits, i.e. "2018-11-01T18:07:55.672" instead of "2018-11-01T18:07:55.6725292Z", and also changes the according 'S' pattern specifiers, i.e. "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'".

Covert RFC3339 DateTime to Date in java

If I understand your question, you can use SimpleDateFormat like so,

String in = "2014-07-21T16:35:27.000Z";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println(sdf.parse(in));


Related Topics



Leave a reply



Submit