How to convert ISO8601 format into milliseconds?

18,994

Solution 1

tl;dr

Instant.parse( "2014-10-23T00:35:14.800Z" )
       .toEpochMilli()

One-Liner In java.time

The java.time framework is built into Java 8 and later. These new classes supplant the old date-time classes bundled with the earliest versions of Java such as java.util.Date/.Calendar. See Tutorial. The java.time classes also supplant the highly successful Joda-Time library, being built by some of the same folks including being led by the same Stephen Colbourne.

An Instant is a moment on the timeline in UTC with a resolution of nanoseconds. You can ask it for a count of milliseconds from its epoch (first moment of 1970 in UTC). But remember that an Instant may have additional data, nanoseconds being finer than milliseconds. So you may be losing data in that tiny fraction of a fraction of a second.

The java.time classes use standard ISO 8601 formats when parsing/generating strings. No need to specify a formatting pattern. The Instant class can directly parse a string.

Instant.parse( "2014-10-23T00:35:14.800Z" )

You can convert that to a count of milliseconds since the epoch of first moment of 1970 in UTC by calling toEpochMilli

Be aware of possible data loss as the Instant class can hold nanoseconds. So extracting milliseconds will be truncating any microseconds or nanoseconds in any fractional second. Your example string has only three digits in the fractional second, so that is only milliseconds. But six or nine digits of decimal fraction would be truncated to three when converted to a count of milliseconds.

long millisFromEpoch = Instant.parse( "2014-10-23T00:35:14.800Z" ).toEpochMilli();

To get elapsed time in terms of hours-minutes-seconds, use the Duration class. Feed its between method a pair of moments in time.

Duration duration = Duration.between( Instant.parse( "2014-10-23T00:35:14.800Z" ) , Instant.now() );

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.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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?

Table of which java.time library to use with which version of Java or Android


One-Liner In Joda-Time

UPDATE: The Joda-Time project is in maintenance mode, with the team advising migration to the java.time classes.

With the Joda-Time 2.5 library:

long millisSinceEpoch = new DateTime( "2014-10-23T00:35:14.800Z" ).getMillis();

Joda-Time parses and generates ISO 8601 strings by default. Joda-Time works in Android. The java.util.Date/.Calendar classes are notoriously troublesome, confusing, and flawed. Avoid them.

Solution 2

So, turns out the answer was simpler than I would have imagined.

private void setTimestamp(String timeCreated) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    try {
        Date timeCreatedDate = dateFormat.parse(timeCreated);
        timeStamp = (String) DateUtils.getRelativeTimeSpanString(timeCreatedDate.getTime(),
                                  System.currentTimeMillis(), 
                                  DateUtils.SECONDS_IN_MILLIS);
    } catch ( ParseException e) {}
}

That'll work.

Share:
18,994
David
Author by

David

Updated on July 23, 2022

Comments

  • David
    David almost 2 years

    I'm pretty surprised that I haven't yet found a really easy way considering how often ISO8601 is used in JSON.

    Basically, I'm taking a string that looks like this: 2014-10-23T00:35:14.800Z and converting it into something like 50 minutes ago.

    First, I have to change 2014-10-23T00:35:14.800Zto 2014-10-23'T'00:35:14.800Z, then I need to convert it to milliseconds, then it is easy.

    My current code:

    private void setTimestamp(String timeCreated) {
        int indexOfT = timeCreated.indexOf('T');
    
        String properFormat = new StringBuilder(timeCreated).insert(indexOfT + 1, "'")
                                                            .insert(indexOfT, "'")
                                                            .toString();
    
        timeStamp = (String) DateUtils.getRelativeTimeSpanString(Long.parseLong(properFormat),
                                      System.currentTimeMillis(), 
                                      DateUtils.SECONDS_IN_MILLIS);
    }
    

    The culprit is Long.parseLong(properFormat). I need to convert properFormat into milliseconds.

  • David
    David over 9 years
    I think I'll definitely use this. Seems like a one-liner tailor-made for my dates.
  • Basil Bourque
    Basil Bourque about 8 years
    Down-voter: Please leave a criticism along with your vote, especially on an accepted Answer.
  • rightaway717
    rightaway717 about 4 years
    Instant is available on Android since API 26 only
  • Basil Bourque
    Basil Bourque about 4 years
    @rightaway717 Most of the functionality of java.time built into Java 8 is back-ported to Java 6 & 7 in the ThreeTen-Backport project, and further adapted for early Android in ThreeTenABP.