Строка даты Android UTC для локальной даты

У меня проблемы с преобразованием строки даты UTC в строку локальной даты в Android. Пример на случай, я ввел строку даты UTC как 2018-02-28T02:42:41Z

Я нахожусь в часовом поясе PST, но когда я попытался преобразовать в местный часовой пояс, это не изменяется. я получил February 28, 2018 02:42 AM что неверно.

public static String convertUTCtoLocalTime(String utcDateString) throws Exception{

    SimpleDateFormat dateFormatter;

    //create a new Date object using the UTC timezone
    Log.v(TAG, "Input utc date:" + utcDateString);
    dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date utcDate = dateFormatter.parse(utcDateString);

    //Convert the UTC date to Local timezone
    dateFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm a");
    dateFormatter.setTimeZone(TimeZone.getDefault());
    String formattedDate = dateFormatter.format(utcDate);
    Log.v(TAG, "convertUTCtoLocalTime: local time:" + formattedDate);

    return lv_dateFormateInLocalTimeZone;
}

Я не до конца понимаю разницу, но подобное преобразование работает в режиме "swift", как показано ниже,

    static func utcDateToLocal(utcdate: String) -> String {
      let dateFormatter = DateFormatter()

      dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" //Input Format 2018-02-28T02:42:41Z
      dateFormatter.timeZone = NSTimeZone(name: "UTC")! as TimeZone
      let UTCDate = dateFormatter.date(from: utcdate)

      dateFormatter.dateFormat = "MMMM dd, yyyy hh:mm a" // Output Format
      dateFormatter.timeZone = TimeZone.current
      let UTCToCurrentFormat = dateFormatter.string(from: UTCDate!)
      return UTCToCurrentFormat
  }

Пример Swift выдает мне "27 февраля 2018 18:42", что является правильным.

Swift использует v3.x и

Android - это Studio 3.1.1 Build #AI-173.4697961, созданный 3 апреля 2018 г. JRE: 1.8.0_152-release-1024-b01 x86_64 JVM: 64-битная виртуальная машина OpenJDK от JetBrains sro Mac OS X 10.13.4

Я запускаю оба примера на одной машине. Любые советы по решению проблемы на Android были бы очень полезны.

1 ответ

static DateTimeFormatter formatter = DateTimeFormatter
        .ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)
        .withLocale(Locale.US);

public static String convertUTCtoLocalTime(String utcDateString) {

    Log.v(TAG, "Input utc date:" + utcDateString);

    String formattedDateTime = Instant.parse(utcDateString)
            .atZone(ZoneId.systemDefault())
            .format(formatter);

    Log.v(TAG, "convertUTCtoLocalTime: local time:" + formattedDateTime);

    return formattedDateTime;
}

Попытайся:

    System.out.println(convertUTCtoLocalTime("2018-02-28T02:42:41Z"));

Выход:

27 февраля 2018 года, 18:42

Используйте встроенные локализованные форматы, а не создавайте собственную строку шаблона формата. Это дает вам некоторую уверенность в том, что формат подходит для рассматриваемой локали, он работает и в других локалях и избавляет вас от подверженной ошибкам задачи написания правильной строки шаблона формата. В локали США длинный формат даты дает полное название месяца (а не только "февраль"), а короткий формат дает время без секунд. В сочетании именно та строка, которую я понял, вы хотели.

Instant Класс анализирует вашу строку UTC без какого-либо явного средства форматирования, что снова избавляет вас от создания строки шаблона формата. Формат ISO 8601. Instant класс и другие классы даты и времени, которые я использую, являются частью java.time, современный Java API даты и времени. Эти классы анализируют ISO 8601 как их значения по умолчанию. И вообще, с современным API гораздо приятнее работать.

Что пошло не так в вашем коде?

Ваше обращение правильно. Когда я запустил его на своем компьютере, он передавал следующую строку Log.v(): convertUTCtoLocalTime: local time:February 27, 2018 06:42 PM, Я считаю, что это было то, что вы ожидали. Я вижу только две потенциальные проблемы:

  1. Если ваш часовой пояс по умолчанию - как получено из TimeZone.getDefault() - это не то, что вы думаете, вы получите неправильный результат. В этом случае, однако, ваш код Swift, скорее всего, даст тот же неправильный результат, и мой код выше наверняка будет.
  2. Ваше возвращенное заявление:

         return lv_dateFormateInLocalTimeZone;
    

    Вы не коснулись переменной с именем lv_dateFormateInLocalTimeZone в том, что идет раньше, поэтому эта переменная не может содержать ваши отформатированные дату и время. Чтобы вернуть его вам понадобится

         return formattedDate;
    

Вопрос: Могу ли я использовать java.time на Android?

Да, java.time прекрасно работает на старых и новых устройствах Android. Это просто требует как минимум Java 6.

  • В Java 8 и более поздних версиях и на более новых устройствах Android (от 26 уровня API, как мне говорят) современный API поставляется встроенным.
  • В Java 6 и 7 получите ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310; см. Ссылки внизу).
  • На (более старой) версии Android используется версия Android ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортируете классы даты и времени из org.threeten.bp с подпакетами.

связи

Другие вопросы по тегам