Iso 8601 String to Date/Time Object in Android

ISO 8601 String to Date/Time object in Android


String dtStart = "2010-10-15T09:27:37Z";  
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
try {
Date date = format.parse(dtStart);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}

This is what you are looking for. There is existing post about this problem.

Converting a String to Java Date in ISO 8601 date-time format


tl;dr

OffsetDateTime.parse( "2001-05-03T00:00:00+00:00" )

Avoid legacy date-time classes

Never use SimpleDateFormat, Date, Calendar, etc. These terrible classes were supplanted years ago by the java.time classes.

ISO 8601

trying to convert a string into an ISO 8601 date-time format

String s1 = "2001-05-03T00:00:00+00:00"

Your Question is quite confused. Your input string is in standard ISO 8601 format. The T in the middle separates the year-month-day from the hour-minute-second, and the +00:00 at the end indicates an offset-from-UTC of zero hours and zero minutes, that is, UTC itself. All standard, all proper.

Perhaps you are conflating strings representing date-time values and date-time objects containing date-time values. A date-time object has no “format”; it has its own internally-defined representation of a date-time value. Only text has a format. A date-time class can parse a formatted string as input, and a date-time class can generate a formatted sting as output, but within the date-time there is no format at all.

OffsetDateTime

The java.time classes use the ISO 8601 formats by default when parsing/generating strings representing date-time values. So no need to specify a formatting pattern for such inputs.

OffsetDateTime odt = OffsetDateTime.parse( "2001-05-03T00:00:00+00:00" ) ;  

See this code run live at IdeOne.com.

odt.toString(): 2001-05-03T00:00Z

Z

There is a common abbreviation for an offset of zero: a simple Z letter, meaning UTC, and pronounced “Zulu”. Example: 2019-02-26T00:44:28Z

The Z is quite commonly used. But if for some reason you prefer the numeric +00:00, use DateTimeFormatter options.

COLON character

By the way, you mentioned the COLON character omitted from the offset: +0000. That is actually tolerated by the ISO 8601 standard. But I do not advise it. I have seen libraries and systems break on such inputs. Best to use full-length, hours and minutes, padding zeros, and the colon character: +00:00 rather than +0000, and -07:00 rather than -7.


About java.time

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.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.

    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7

    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android

    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Convert any ISO-8601 format to a readable format in Android


java.time and desugaring or ThreeTenABP

You can use DateTimeFormatter and the other classes from java.time, the modern Java date and time API, on Android API level 21 and up in two ways:

  1. Through desugaring.
  2. Through the backport; there is even an Android adaptation of it, ThreeTenABP, already mentioned by chrylis. It’s ThreeTen for JSR-310, where java.time was first described, and ABP for Android backport.

For both ways see the links at the bottom.

Code

You don’t even need to specify a formatter.

    String stringWeGot = "2020-09-03T17:03:11.719566Z";
Instant parsed = Instant.parse(stringWeGot);
System.out.println(parsed);

Output:

2020-09-03T17:03:11.719566Z

Or with your other example string:

    String stringWeGot = "2021-03-05T18:30:00Z";

2021-03-05T18:30:00Z

The classes of java.time parse the most common ISO 8601 variants as their default, that is, without an explicit formatter. Presence or absence of from 0 through 9 decimals on the seconds is built in, even the presence or absence of the seconds themselves. Both Instant and OffsetDateTime can be used in the manner shown in the code.

Warning! If you do opt for one or more formatters for one reason or another, never hardcode Z as a literal in the format pattern string. Z is an offset (of zero) from UTC and must be parsed as such, or you get incorrect results on the vast majority of Android devices.

Also when it comes to counting days, java.time is far superior to the old and poorly designed classes like Calendar. EDIT: Your method for counting whole days until the due date in the device time zone is correct. Just for reference, my way of doing it would be:

    ZoneId zone = ZoneId.systemDefault();
ZonedDateTime today = ZonedDateTime.now(zone);
ZonedDateTime dueDate = parsed.atZone(zone);
long daysUntilDue = ChronoUnit.DAYS.between(today, dueDate);
System.out.println(daysUntilDue);

Using your example string of 2021-03-05T18:30:00Z and running in Europe/Copenhagen time zone just now the result was:

181

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
  • Java 8+ APIs available through desugaring
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

How to get current moment in ISO 8601 format with date, hour, and minute?

Use SimpleDateFormat to format any Date object you want:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

Using a new Date() as shown above will format the current time.

How to parse iso8601 date-time in android kotlin or java

My issue solved
Thanks @OleV.V.

Solution
This pattern: "yyyyMMdd'T'HHmmss"

Converting ISO 8601-compliant String to java.util.Date

Unfortunately, the time zone formats available to SimpleDateFormat (Java 6 and earlier) are not ISO 8601 compliant. SimpleDateFormat understands time zone strings like "GMT+01:00" or "+0100", the latter according to RFC # 822.

Even if Java 7 added support for time zone descriptors according to ISO 8601, SimpleDateFormat is still not able to properly parse a complete date string, as it has no support for optional parts.

Reformatting your input string using regexp is certainly one possibility, but the replacement rules are not as simple as in your question:

  • Some time zones are not full hours off UTC, so the string does not necessarily end with ":00".
  • ISO8601 allows only the number of hours to be included in the time zone, so "+01" is equivalent to "+01:00"
  • ISO8601 allows the usage of "Z" to indicate UTC instead of "+00:00".

The easier solution is possibly to use the data type converter in JAXB, since JAXB must be able to parse ISO8601 date string according to the XML Schema specification. javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z") will give you a Calendar object and you can simply use getTime() on it, if you need a Date object.

You could probably use Joda-Time as well, but I don't know why you should bother with that (Update 2022; maybe because the entire javax.xml.bind section is missing from Android's javax.xml package).

Parse a date-time string in ISO 8601 format without offset-from-UTC

Your date string and DateFormat need to match. For your input "2016-05-21T00:00:00", the correct DateFormat is:

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

How can I change java.util.Date to ISO String using ThreeTenABP

A ThreetenABP-solution can look like this:

java.util.Date d = ...;
org.threeten.bp.Instant instant = org.threeten.bp.DateTimeUtils.toInstant(d);
String iso = instant.toString();

If you wish more control over formatting then you can convert the instant to a ZonedDateTime (or better to an OffsetDateTime) and use a dedicated DateTimeFormatter.



Related Topics



Leave a reply



Submit