java .time и ThreeTenABP
Пуленепробиваемый способ - переход на java .time, современный Java API даты и времени.
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse("06/05/2020", dateFormatter);
System.out.println(date);
Вывод это:
2020-06-05
Что пошло не так в вашем коде?
Это определенно проблема часового пояса. Однако это не воспроизводится наивным запуском вашего кода. Происходит что-то еще, и мы можем только догадываться, что именно. Я представлю несколько способов, как это могло произойти.
Первая возможность, часовой пояс по умолчанию вашей JVM мог измениться в процессе. Чтобы продемонстрировать:
TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
Date date = sdf.parse("06/05/2020");
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
System.out.println(date);
Четверг, 04 июня 18:00:00 MDT 2020
Честно говоря, это не полный день неправильно, это 6 часов. Это достаточно плохо, и определенно день недели и день месяца неправильные. Обратите внимание, что настройка часового пояса JVM могла быть изменена из совершенно другой части вашей программы или из другой программы, работающей в той же JVM. Произошло следующее: SimpleDateFormat
получил часовой пояс JVM по умолчанию, то есть UT C. Итак разобрал дату в первый момент 5 июня в UT C. На данный момент в Северной Америке все еще 4 июня. Затем, когда мы печатаем Date
, Date.toString()
захватывает (измененный) часовой пояс JVM и использует его для рендеринга строки. Таким образом, мы получили время MDT (летнее время в горах Северной Америки), а не время UT C, которое использовалось для синтаксического анализа.
Нам не нужно что-то столь же drasti c, как установка часового пояса для демонстрации всей JVM. Достаточно установить часовой пояс форматтера.
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
Date date = sdf.parse("06/05/2020");
System.out.println(date);
При работе в Америке / часовом поясе Эдмонтона:
Четверг, 04 июня 18:00:00 MDT 2020
Что происходит, в основном то же, что и выше.
Вопрос: Разве java .time не требует Android уровня API 26?
java. time отлично работает как на старых, так и на новых устройствах Android. Для этого просто требуется как минимум Java 6 .
- В Java 8 и более поздних версиях и на более новых Android устройствах (начиная с уровня API 26) создается современный API -in.
- В не- Android Java 6 и 7 получите ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. ссылки внизу).
- На (более ранней) Android используйте Android версию ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортировали классы даты и времени из
org.threeten.bp
с подпакетами.
Ссылки