2017-01-26 17 views
11

Код ниже дает другой результат по Нуге и пред-Нуге. Взгляните и попробуйте сами, если хотите. Я был бы признателен, если бы кто-нибудь мог объяснить мне, почему и дать решение.GregorianCalendar setFirstDayOfWeek не влияет на WEEK_OF_YEAR на pre Nougat

Я хочу правильное значение WEEK_OF_YEAR, в зависимости от первого дня недели, на всех версиях Android. У меня есть приложение для листа времени, и я часто использую gregorianCalendar, поэтому мне не хочется переключаться на другой класс/lib.

//default first day of the week is Monday for replication. I live in the Netherlands, it's weird. 
    Locale l = new Locale("nl", "NL"); 

    GregorianCalendar test = new GregorianCalendar(l); 
    test.set(Calendar.YEAR, 2017); 
    test.set(Calendar.MONTH, 0); 
    test.set(Calendar.DAY_OF_MONTH, 29);//this is a Sunday 

    int week = test.get(Calendar.WEEK_OF_YEAR);//should be 4 
    test.setFirstDayOfWeek(1);//Set it to Sunday 
    int week2 = test.get(Calendar.WEEK_OF_YEAR);//should be 5 but is 4 below nougat??? 
+0

спасибо за разъяснение. Я не думаю, что мой ответ будет полезным для вас сейчас, кроме общего кив в сторону проблемы (подходящее приложение Nuggat и локаль системы). Чтобы привлечь лучшие ответы, возможно, вы можете прояснить что-то еще. Является ли установка Locale в вашем примере кода просто для репликации проблемы или это то, что вы хотели бы сделать в своем приложении? –

+0

Спасибо в любом случае. Локаль просто реплицирует проблему. –

ответ

3

Если вы посмотрите на release notes for Nougat вы можете видеть, что есть расширенная поддержка Locales.

Особенно

До Android 7.0, Android может не всегда успешно совпадают приложения и системные локали.

Я тоже это заметил на своем собственном устройстве. Мой телефон настроен на английский (Австралия). До Нуга,

DateTimeFormat.forPattern("dd MMMM").print(new LocalDate(2017,1,29)); 

не будет печатать 29 Jan (без полной остановки/период), но после того, как он печатает Нуга 29 Jan. (с периодом).

Хотя мне трудно дать точную информацию, похоже, что это то, что происходит в вашем случае. Post-Nougat, телефон может лучше соответствовать местным приложениям и системам, включая первый день недели для вашего Locale. В любом случае переход с помощью отладчика для поиска основной причины не будет работать, потому что вызов обрабатывается внутри libcore, а не класс Java, открытый в исходном коде.

Если Android устройство неправильно передают в первый день года/первая неделя года, было бы мало вы можете сделать, кроме работы вокруг него:

if (android.os.Build.VERSION.SDK_INT < 24) { 
    //pre-Nougat logic 
} 
else { 
    //Nougat/post-Nougat logic 
} 

Вы могли бы также, возможно, попробуйте использовать enhanced replacement for GregorianCalendar (добавлен в SDK 24), чтобы исправить вашу проблему.

Если вы используете классы как Joda-time или использовать новые JSR-310 классы (через Backport ThreeTen) вы могли бы получить то, что вы хотите без того, чтобы работать вокруг GregorianCalendar. В целом эти классы намного проще в использовании и менее подвержены ошибкам. Многие разработчики уже отказались от java.util.Calendar и java.util.Date из-за таких проблем. Пожалуйста, смотрите ответы to this canonical question для деталей

Если вы должны были использовать Joda, вы можете использовать LocalDate.fromCalendarFields(test) для преобразования GregorianCalendar объекта в LocalDate. Эти классы используют стандарт ISO, где первый день недели всегда в понедельник. Затем вы должны написать нужную вам логику. Тогда вопрос с GregorianCalendar будет «изолирован» в простой проблеме с получением первой недели года для данного локали. Если ваше приложение включает вызовы на сервер, вы можете использовать первый день недели вместо вызова API.

Update:

Примечание поведение временных зон была обновлена ​​в Android O:

Дополнительные локали и изменения, связанные с интернационализацией заключаются в следующем:

Название зоны разборе изменилось. Раньше на устройствах Android использовалось системное значение часов, отобранное во время загрузки, для кэширования имен часовых поясов, используемых для разбора даты. В результате разбор может отрицательно сказаться, если системные часы были неправильными во время загрузки или в других, более редких случаях. Теперь в обычных случаях логика синтаксического анализа использует ICU и текущее системное значение часов при разборе имен часовых поясов. Это изменение дает более правильные результаты, которые могут отличаться от предыдущих версий Android, когда ваше приложение использует такие классы, как SimpleDateFormat. Android O обновляет версию ICU до версии 58.

+0

В принципе, я хочу, чтобы значение WEEK_OF_YEAR было правильным, в зависимости от первого дня недели, на всех версиях Android. У меня есть приложение timehseet, и я часто использую gregorianCalendar, поэтому мне не хочется переключаться на другой класс/lib. –

-1

Из чего я думаю, что проблема заключается в том, что вы устанавливаете месяц.

// Здесь, в месяце Параметр, в котором вы передаете 0, как значение, которое может создать проблему, потому что, хотя массив начинается с 0, входной параметр, который принимает этот Calendar.MONTH, составляет от 1 до 12. Попробуйте изменить это ,

Или Вы также можете изменить его к этому для установки его в январе, как использование месяц

test.set(Calendar.MONTH, Calendar.JANUARY); 

// Также здесь, в этой строке попытаться изменить к

test.setFirstDayOfWeek(Calendar.SUNDAY);//Set it to Sunday 

Это должно решить ваши проблема.

+1

Мне жаль, приятель, это неправда. Значение 'Calendar.JANUARY' также равно 0. –

+0

Единственная причина, по которой я говорю использовать Calendar.JANUARY, состоит в том, что если предположить, что значение JANUARY изменяется от 0 до некоторого другого значения, тогда ваш код не понадобится для обновления. –

Смежные вопросы