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:
- ISO_INSTANT
- 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 thatZ
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.
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
Simple Way to Count Character Occurrences in a String
How to Determine If a List Is Sorted in Java
Byte Array and Int Conversion in Java
Read a File Line by Line in Reverse Order
JSONmanagedreference VS JSONbackreference
Java: Convert String to Timestamp
Why Does Inputstream#Read() Return an Int and Not a Byte
How to Change Timezone for a Java.Util.Calendar/Date
Using Setvalueat to Recreate Mutually Exclusive Check Boxes
Uses for the Java Void Reference Type
Passing Command Line Unicode Argument to Java Code
How to Add a Utf-8 Bom in Java
Convert a Date Format in Epoch
How to Tell Jackson to Ignore a Property for Which I Don't Have Control Over the Source Code
Rounding a Double to Turn It into an Int (Java)