Ответ 1
Если вы посмотрите на примечания к выпуску для Nougat, вы увидите, что улучшена поддержка Locales.
Особенно,
До Android 7.0 Android не всегда мог успешно соответствовать локалям приложений и систем.
Я тоже это заметил на своем собственном устройстве. Мой телефон настроен на английский (Австралия). До Нуги,
DateTimeFormat.forPattern("dd MMMM").print(new LocalDate(2017,1,29));
будет печатать 29 Jan
(без полной остановки/периода), но после Nougat он печатает 29 Jan.
(с периодом).
Хотя мне трудно дать точную информацию, кажется, что это то, что происходит в вашем случае. Post-Nougat, телефон может лучше соответствовать местным приложениям и системам, включая первый день недели для вашего Locale. В любом случае переход с отладчиком для поиска основной причины не будет работать, потому что вызов обрабатывается внутри libcore
, а не класс Java, открытый в исходном коде.
Если Android-устройство неправильно сообщает о первом дне года/первой неделе года, вы можете сделать что-то мало, кроме работы вокруг него:
if (android.os.Build.VERSION.SDK_INT < 24) {
//pre-Nougat logic
}
else {
//Nougat/post-Nougat logic
}
Возможно, вы также попытаетесь использовать расширенную замену для GregorianCalendar (добавлена в SDK 24), чтобы исправить вашу проблему.
Если вы используете классы типа Joda-time или используйте новый JSR-310 (через обратный порт ThreeTen) вы можете получить то, что хотите, без необходимости работать вокруг GregorianCalendar
. В целом эти классы намного проще в использовании и менее подвержены ошибкам. Многие разработчики уже отказались от java.util.Calendar
и java.util.Date
из-за таких проблем. Подробнее об этом
Если вы собираетесь использовать Joda, вы можете использовать LocalDate.fromCalendarFields(test)
для преобразования вашего объекта GregorianCalendar
в LocalDate
. Эти классы используют стандарт ISO, где первый день недели всегда в понедельник. Затем вы должны написать нужную вам логику. Тогда проблема с GregorianCalendar
была бы "изолирована" в простой проблеме с получением первой недели года для данного локали. Если ваше приложение включает вызовы на сервер, вы можете использовать первый день недели вместо вызова API.
Update:
Поведение часового пояса в примечании обновлено в Android O:
Дополнительные изменения, связанные с локалью и интернационализацией, следующие:
Разбор имени часового пояса изменился. Раньше на устройствах Android использовалось системное значение часов, отобранное во время загрузки, для кэширования имен часовых поясов, используемых для разбора даты. В результате разбор может отрицательно сказаться, если системные часы были неправильными во время загрузки или в других, более редких случаях. Теперь в обычных случаях логика синтаксического анализа использует ICU и текущее значение системного такта при разборе имен часовых поясов. Это изменение дает более правильные результаты, которые могут отличаться от предыдущих версий Android, когда ваше приложение использует такие классы, как SimpleDateFormat. Android O обновляет версию ICU до версии 58.