Строка даты 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
, Я считаю, что это было то, что вы ожидали. Я вижу только две потенциальные проблемы:
- Если ваш часовой пояс по умолчанию - как получено из
TimeZone.getDefault()
- это не то, что вы думаете, вы получите неправильный результат. В этом случае, однако, ваш код Swift, скорее всего, даст тот же неправильный результат, и мой код выше наверняка будет. Ваше возвращенное заявление:
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
с подпакетами.
связи
- Учебник Oracle: Дата и время, объясняющие, как использовать
java.time
, - Запрос спецификации Java (JSR) 310, где
java.time
был впервые описан. - ThreeTen Backport проект, бэкпорт
java.time
в Java 6 и 7 (ThreeTen для JSR-310). - ThreeTenABP, Android-версия ThreeTen Backport
- Вопрос: Как использовать ThreeTenABP в Android Project, с очень подробным объяснением.
- Статья в Википедии: ISO 8601