Reputation: 31630
I have the following date: 2011-08-12T20:17:46.384Z
. What format is this? I'm trying to parse it with Java 1.4 via DateFormat.getDateInstance().parse(dateStr)
and I'm getting
java.text.ParseException: Unparseable date: "2011-08-12T20:17:46.384Z"
I think I should be using SimpleDateFormat for parsing, but I have to know the format string first. All I have for that so far is yyyy-MM-dd
, because I don't know what the T
means in this string--something time zone-related? This date string is coming from the lcmis:downloadedOn
tag shown on Files CMIS download history media type.
Upvotes: 686
Views: 940323
Reputation: 29
In JavaScript:
let isoDateTimeString = new Date().toISOString();
Description
Date/time format like "YYYY-MM-DDThh:mm:ss.SSSZ" is ISO 8601 date/time format.
Upvotes: 2
Reputation: 78945
You do not need DateTimeFormatter
to parse the given date-time string.
Java SE 8 Date-Time API(java.time
API or the modern Date-Time API) is based on ISO 8601 and does not require using a DateTimeFormatter
object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.
The Z
in the string is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC
timezone (which has the timezone offset of +00:00
hours).
The T
in the string is just the Date-Time separator as per the ISO-8601 standards.
Demo:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
String strDateTime = "2011-08-12T20:17:46.384Z";
Instant instant = Instant.parse(strDateTime);
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime);
System.out.println(instant);
System.out.println(odt);
System.out.println(zdt);
}
}
Output:
2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z
Learn more about java.time
, the modern Date-Time API* from Trail: Date Time.
The legacy Date-time API (java.util
Date-Time API and their formatting API, SimpleDateFormat
) are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
For the sake of completeness, I've written a solution to parse this Date-Time string using the legacy API.
Do not use 'Z'
in the pattern with the Date-Time parsing/formatting API.
As already described above, Z
(without quotes) is the timezone designator for zero-timezone offset whereas 'Z'
is just a character literal and it does not hold any meaning. Use the format, y-M-d'T'H:m:s.SSSXXX
. Check the documentation to learn more about these symbols.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "2011-08-12T20:17:46.384Z";
SimpleDateFormat sdf = new SimpleDateFormat("y-M-d'T'H:m:s.SSSXXX", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
// ...
}
}
Note that a java.util.Date
object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT
(or UTC). Since it does not hold any format and timezone information, it applies the format, EEE MMM dd HH:mm:ss z yyyy
and the JVM's timezone to return the value of Date#toString
derived from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat
with the desired format and the applicable timezone e.g.
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String formatted = sdf.format(date);
System.out.println(formatted); // 2011-8-12T20:17:46.384Z
Quoted below is a notice at the Home Page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Again, for the sake of completeness, I've written a solution to parse this Date-Time string using the Joda Date-Time API.
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String dateTimeStr = "2011-08-12T20:17:46.384Z";
DateTimeFormatter dtf = DateTimeFormat.forPattern("y-M-d'T'H:m:s.SSSZ").withOffsetParsed();
DateTime dateTime = dtf.parseDateTime(dateTimeStr);
System.out.println(dateTime);
}
}
Output:
2011-08-12T20:17:46.384Z
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Upvotes: 12
Reputation: 123
Z represent UTC time zone. With java8+, you can simply use Instant.
public static void main(String[] args) {
String time = "2022-06-08T04:55:01.000Z";
System.out.println(Instant.parse(time).toEpochMilli());
}
Upvotes: 3
Reputation: 6778
FOR JODA TIME
String datetimeString = "2099-12-31T14:20:04Z";
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZoneUTC();
DateTime dateTime = formatter.parseDateTime(datetimeString);
System.out.println("Parsed date and time: " + dateTime);
Upvotes: 0
Reputation: 338171
Standard ISO 8601 format is used by your input string.
Instant.parse ( "2011-08-12T20:17:46.384Z" )
This format is defined by the sensible practical standard, ISO 8601.
The T
separates the date portion from the time-of-day portion. The Z
on the end means UTC (that is, an offset-from-UTC of zero hours-minutes-seconds). The Z
is pronounced “Zulu”.
The old date-time classes bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. Avoid them.
Instead, use the java.time framework built into Java 8 and later. The java.time classes supplant both the old date-time classes and the highly successful Joda-Time library.
The java.time classes use ISO 8601 by default when parsing/generating textual representations of date-time values.
The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds. That class can directly parse your input string without bothering to define a formatting pattern.
Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Upvotes: 188
Reputation: 2126
If you guys are looking for a solution for Android, you can use the following code to get the epoch seconds from the timestamp string.
public static long timestampToEpochSeconds(String srcTimestamp) {
long epoch = 0;
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Instant instant = Instant.parse(srcTimestamp);
epoch = instant.getEpochSecond();
} else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = sdf.parse(srcTimestamp);
if (date != null) {
epoch = date.getTime() / 1000;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return epoch;
}
Sample input: 2019-10-15T05:51:31.537979Z
Sample output: 1571128673
Upvotes: 4
Reputation: 139
@John-Skeet gave me the clue to fix my own issue around this. As a younger programmer this small issue is easy to miss and hard to diagnose. So Im sharing it in the hopes it will help someone.
My issue was that I wanted to parse the following string contraining a time stamp from a JSON I have no influence over and put it in more useful variables. But I kept getting errors.
So given the following (pay attention to the string parameter inside ofPattern();
String str = "20190927T182730.000Z"
LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );
Error:
Exception in thread "main" java.time.format.DateTimeParseException: Text
'20190927T182730.000Z' could not be parsed at index 19
The problem? The Z at the end of the Pattern needs to be wrapped in 'Z' just like the 'T' is. Change
"yyyyMMdd'T'HHmmss.SSSZ"
to "yyyyMMdd'T'HHmmss.SSS'Z'"
and it works.
Removing the Z from the pattern alltogether also led to errors.
Frankly, I'd expect a Java class to have anticipated this.
Upvotes: -2
Reputation: 1499760
The T is just a literal to separate the date from the time, and the Z means "zero hour offset" also known as "Zulu time" (UTC). If your strings always have a "Z" you can use:
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Or using Joda Time, you can use ISODateTimeFormat.dateTime()
.
Upvotes: 753
Reputation: 894
This technique translates java.util.Date to UTC format (or any other) and back again.
Define a class like so:
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class UtcUtility {
public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();
public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
return dateTimeFormatter.parseDateTime(date).toDate();
}
public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
return format(dateTimeFormatter, date.getTime());
}
private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
DateTime dateTime = new DateTime(timeInMillis);
String formattedString = dateTimeFormatter.print(dateTime);
return formattedString;
}
}
Then use it like this:
Date date = format(UTC, "2020-04-19T00:30:07.000Z")
or
String date = parse(UTC, new Date())
You can also define other date formats if you require (not just UTC)
Upvotes: -1
Reputation: 27
You can use the following example.
String date = "2011-08-12T20:17:46.384Z";
String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
String outputPattern = "yyyy-MM-dd HH:mm:ss";
LocalDateTime inputDate = null;
String outputDate = null;
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);
inputDate = LocalDateTime.parse(date, inputFormatter);
outputDate = outputFormatter.format(inputDate);
System.out.println("inputDate: " + inputDate);
System.out.println("outputDate: " + outputDate);
Upvotes: 1
Reputation: 420
There are other ways to parse it rather than the first answer. To parse it:
(1) If you want to grab information about date and time, you can parse it to a ZonedDatetime
(since Java 8) or Date
(old) object:
// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);
or
// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);
Date myDate = df.parse("2011-08-12T20:17:46.384Z");
(2) If you don't care the date and time and just want to treat the information as a moment in nanoseconds, then you can use Instant
:
// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");
Upvotes: 16
Reputation: 14053
Not sure about the Java parsing, but that's ISO8601: http://en.wikipedia.org/wiki/ISO_8601
Upvotes: 30