Как преобразовать формат ISO8601 в миллисекунды?

Я очень удивлен, что я еще не нашел очень простой способ, учитывая, как часто ISO8601 используется в JSON.

в основном, я беру строку, которая выглядит так: 2014-10-23T00:35:14.800Z и преобразование его во что-то вроде 50 minutes ago.

во-первых, я должен изменить 2014-10-23T00:35:14.800Zto 2014-10-23'T'00:35:14.800Z, тогда мне нужно преобразовать его в миллисекунды, тогда это легко.

мой текущий код:

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);
}

виновником ДТП является Long.parseLong(properFormat). Мне нужно преобразовать properFormat в миллисекунды.

2 ответов


tl; dr

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

однострочный на java.время

на java.время framework встроен в Java 8 и более поздние версии. Эти новые классы вытесняют старые классы даты-времени в комплекте с самыми ранними версиями Java, такими как java.утиль.Дата./Календарь. См.учебник. Ява.классы времени также вытесняют очень успешные Joda Времени библиотека, строится некоторыми из тех же людей, в том числе во главе с тем же Стивен Colbourne.

An Instant момент на временной шкале в UTC с разрешением наносекунд. Ты можешь!--33-->попросите его отсчет миллисекунд из его эпохи (первый момент 1970 года в UTC). Но помните, что Instant может иметь дополнительные данные, наносекунды быть тоньше, чем миллисекунды. Так ты возможно потеря данных в этой крошечной фракции на долю секунды.

java.классы времени используют стандартные форматы ISO 8601 при анализе / генерации строк. Нет необходимости указывать шаблон форматирования. The Instant класс можно напрямую парсить строку.

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

вы можете преобразовать это в количество миллисекунд с эпохи первого момента 1970 года в UTC, вызвав toEpochMilli

имейте в виду о возможной потере данных, как Instant класс может содержать наносекунд. Поэтому извлечение миллисекунды будут усекать любые микросекунды или наносекунды в любую долю секунды. В вашей строке примера есть только три цифры в дробной секунде, так что это всего лишь миллисекунды. Но шесть или девять цифр десятичной дроби будут усечены до трех при преобразовании в счет миллисекунд.

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

чтобы получить истекшее время с точки зрения часов-минут-секунд, используйте Duration класса. Накорми ее between метод пара моментов в время.

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

Однострочный В Joda-Time

обновление: проект Joda-Time находится в режиме обслуживания, команда консультирует миграцию на java.классы время.

С Joda Времени 2.5 библиотека:

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

Joda-время анализирует и генерирует ISO 8601 строк по умолчанию. Joda-Time работает в Android. Ява.утиль.Дата./Календарные классы, как известно, хлопотно, запутанно, и недостатки. Избегать их.


Итак, оказывается, ответ был проще, чем я мог себе представить.

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) {}
}

Это сработает.