Не могу преобразовать iso8601 в текущую дату Android

У меня есть 3 сообщения, это сообщение было отправлено последовательно, сервер дал мне 4 времени ISO8601:

2017-01-11T12:34:21.948631
2017-01-11T12:34:22.425915
2017-01-11T12:34:22.954749
2017-01-11T12:34:23.473965

Моя логика конвертируется в текущую дату

public class ISO8601{
    static SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS");

    String isodate;
    long timestamp = 0;

    public ISO8601(String isodate){
        dateformat.setTimeZone(TimeZone.getTimeZone("UTC"));

        this.isodate = isodate;

        try {
            Date date = dateformat.parse(this.isodate);
            timestamp = date.getTime();


        } catch (ParseException e) {
            e.printStackTrace();

        }
    }

    public long getTime(){
        return timestamp;
    }

}

класс для преобразования на сегодняшний день

public class HelperMethods {
  public static CharSequence getFormatTime(long time) {
        DateFormat sdf = new SimpleDateFormat("hh:mm:ss yyyy-MM-dd");
        Date netDat = new Date(time);
        return sdf.format(netDat);
    }
}

Теперь я пытаюсь использовать этот класс и метод для преобразования ISO8601 в обычное время.

Log.e("1", String.valueOf(HelperMethods.getFormatTime(new ISO8601("2017-01-11T12:34:21.948631").getTime())));
        Log.e("2", String.valueOf(HelperMethods.getFormatTime(new ISO8601("2017-01-11T12:34:22.425915").getTime())));
        Log.e("3", String.valueOf(HelperMethods.getFormatTime(new ISO8601("2017-01-11T12:34:22.954749").getTime())));
        Log.e("4", String.valueOf(HelperMethods.getFormatTime(new ISO8601("2017-01-11T12:34:23.473965").getTime())));

И он выводит:

01:50:09 2017-01-11
01:41:27 2017-01-11
01:50:16 2017-01-11
01:42:16 2017-01-11

Если я сделаю временную метку * 1000L следующим образом:

public static CharSequence getFormatTime(long time) {
        DateFormat sdf = new SimpleDateFormat("hh:mm:ss yyyy-MM-dd");
        Date netDat = new Date(time * 1000L);
        return sdf.format(time);
    }

Он выводит:

09:00:31 48999-02-14
08:05:15 48999-02-08
10:59:09 48999-02-14
09:42:45 48999-02-09

Я не могу понять, почему я не могу быстро преобразовать дату


person g71132    schedule 11.01.2017    source источник
comment
посмотрите, поможет ли это: stackoverflow.com/a/10621553/2074763   -  person Amey Shirke    schedule 11.01.2017
comment
Возможный дубликат Преобразование формата строки даты и времени iso8601 в дату в Java   -  person W4R10CK    schedule 11.01.2017
comment
@Selvin спасибо за ответ. оказывается сервер выдает мне не правильный ISO8601. Его формат должен выглядеть как 2017-01-11T12:34:21.948631+01:00 ?   -  person g71132    schedule 11.01.2017
comment
@Selvin, я пытался сделать так new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS");, но у меня та же дата, что и в моем вопросе   -  person g71132    schedule 11.01.2017
comment
Класс SimpleDateFormat здесь не подходит, потому что ваш ввод точен до микросекунд, но ваш API ограничен только миллисекундами, поэтому используйте .SSS в конце вашего шаблона (потеряя последние 3 цифры!). И не используйте h, а H для 24-часового формата (как требует ISO-8601).   -  person Meno Hochschild    schedule 11.01.2017
comment
@MenoHochschild спасибо за ответ, я попытался сделать эту строку new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");, но у меня столько же времени, сколько и на мой вопрос 01:50:09 2017-01-11, 01:41:27 2017-01-11, 01:50:16 2017-01-11, 01:42:16 2017-01-11   -  person g71132    schedule 11.01.2017


Ответы (1)


Первое, что следует отметить:

SimpleDateFormat может обрабатывать только миллисекунды, а не микросекунды. Итак, если вы хотите потерять последние 3 цифры вашего ввода ISO-8601, вы можете проанализировать его с помощью этого шаблона:

SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

Обратите внимание, что в этом шаблоне используется «H» для 24-часового формата, а не «h» для 12-часового формата. В противном случае введенный час 12 стал бы нулевым часом.

Следующий шаг: похоже, вы хотите интерпретировать ввод в формате UTC, установив часовой пояс в своем экземпляре SimpleDateFormat. Ясно, что ввод не имеет ни завершающей буквы «Z» (которая должна интерпретироваться как UTC+00:00 в соответствии с ISO), ни какой-либо другой информации о смещении. Это означает: интерпретация как UTC является ВАШЕЙ интерпретацией. В случае сомнений обратитесь к документам/спецификациям поставщика.

Затем вы хотите отформатировать проанализированный экземпляр Date в другой формат. Но здесь вы снова используете «h». Почему? Указание 12-часового формата без маркера am/pm не имеет смысла, поскольку результат неоднозначен. 01:00 будет либо ночью, либо ранним днем, если это означает 12-часовой формат.

Я уже говорил вам, что неправильный символ (здесь «h») переведет 12-й час в нулевой час. Если вы отформатируете такой час В ВАШЕМ ЧАСОВОМ ПОЯСЕ ПО УМОЛЧАНИЮ (ваш вспомогательный метод форматирования не устанавливает какой-либо явный часовой пояс), то к нему будет добавлено смещение. Я думаю, что часовой пояс вашей системы использует смещение в один час, что объясняет окончательный отформатированный результат, в котором вы получаете час 1.

person Meno Hochschild    schedule 11.01.2017