Как конвертировать GMT +09: 00 в местное время? - PullRequest
0 голосов
/ 24 июня 2019

Когда я печатаю дату, полученную с сервера, она показывает Mon Jun 24 16:15:31 GMT+09:00 2019

val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date: Date? = formatter.parse(checkedDate) // date from server
val transformedDate = ("${String.format("%02d", date!!.month + 1)}.${String.format("%02d", date!!.date)}.${date.year + 1900}")
val title: String? = ("$transformedDate")

val longGmtTime = date.time
val mZone = TimeZone.getDefault()
val offset = mZone.getOffset(longGmtTime)
val longLocalTime = longGmtTime + offset - (9 * HOUR)

val localDate = Date() // local date
localDate.time = longLocalTime
val localFormatTime = formatter.format(localDate)
val transformedLocalDate = ("${String.format("%02d", localDate!!.month + 1)}.${String.format("%02d", localDate!!.date)}.${localDate.year + 1900}")

И это дает мне server time: 2019-06-24 16:15:31 -> 06.24.2019, local time(Asia/Seoul)-> 2019-06-25 01:15:30 ->06.25.2019 за результат.

Время сервера и местное время должны совпадать. Но местное время показывает где-то еще.

В чем проблема?

Ответы [ 2 ]

3 голосов
/ 24 июня 2019

В чем проблема?

Полный список проблем включает в себя:

  • Вы используете плохо разработанные и давно устаревшие классы даты и времени Java Date, TimeZone и SimpleDateFormat.
  • Вы используете устаревшие методы getMonth, getDate и getYear класса Date. Эти методы работают ненадежно во всех часовых поясах, что является основной причиной, по которой они устарели.
  • Вы переводите часовой пояс вручную, используя сложение, вычитание и умножение. Математика даты и времени подвержена ошибкам, и вы всегда должны оставлять ее проверенным библиотечным методам.
  • Количество миллисекунд, полученное с Date.getTime, относится к периоду 1970-01-01T00: 00: 00 UTC. Это уникальный момент времени, не зависящий от часового пояса, поэтому нет смысла добавлять и вычитать из подсчета миллисекунд для преобразования часового пояса.
  • Я могу воспроизвести ваш результат, если для часового пояса JVM по умолчанию установлено значение Азия / Сеул, и предположим, что HOUR равно 0 (или некоторому значению в диапазоне от 0 до 111). Я предполагаю, что вы хотели, чтобы HOUR обозначало количество миллисекунд в час, 3 600 000 (по крайней мере, обычно существуют исключения).
  • Вы форматировали свою дату, объединяя результаты звонков на Strirg.format. Лучше оставить форматирование в специализированном форматере даты.

Исправление: java.time

    ZoneId serverTimeZone = ZoneId.of("Asia/Seoul");
    DateTimeFormatter serverFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    ZoneId clientTimeZone = ZoneId.systemDefault();

    String checkedDate = "2019-06-24 16:15:31";
    ZonedDateTime serverDateTime = LocalDateTime.parse(checkedDate, serverFormatter)
            .atZone(serverTimeZone);
    ZonedDateTime clientDateTime = serverDateTime.withZoneSameInstant(clientTimeZone);
    System.out.println("clientDateTime: " + clientDateTime);

Извините, что я могу писать и запускать только код Java, я надеюсь, что вы переведете. С часовым поясом моего JVM, установленным в Азия / Сеул, я получаю:

clientDateTime: 2019-06-24T16: 15: 31 + 09: 00 [Азия / Сеул]

Время сервера и время клиента совпадают, как вы просили. Если вместо этого я сохраню свой часовой пояс, я получу:

clientDateTime: 2019-06-24T09: 15: 31 + 02: 00 [Европа / Копенгаген]

Итак, происходит конверсия.

Для форматирования даты:

    DateTimeFormatter displayFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
            .withLocale(Locale.forLanguageTag("ko-KR"));
    String transformedLocalDate = clientDateTime.format(displayFormatter);
    System.out.println("transformedLocalDate: " + transformedLocalDate);

transformedLocalDate: 2019. 6. 24.

Или, если вы настаиваете на month.date.year:

    DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern("MM.dd.u");

transformedLocalDate: 24.06.2019

Еще одна рекомендация будет заключаться в том, чтобы ваш сервер доставлял строку даты и времени в формате UTC в формате ISO 8601. Это будет похоже на 2019-06-24T07:15:31Z на данный момент, используемый в примерах.

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

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

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

Ссылки

0 голосов
/ 24 июня 2019

Вы должны указать часовой пояс сервера настройки вместо вашего устройства (по умолчанию)

...