Календарь возвращает плохое начало недели на некоторых устройствах Android

Я хотел получить дату первого дня текущей недели. Итак, я реализовал это следующим образом:

fun getFirstDayInCurrentWeek(): Date {
    val calendar = Calendar.getInstance()
    calendar.clear(MILLISECOND)
    calendar.clear(SECOND)
    calendar.clear(MINUTE)
    calendar.set(HOUR_OF_DAY, 0)
    calendar.set(DAY_OF_WEEK, 1)
    return calendar.time
}

Он работает на большинстве устройств, но иногда возвращает дату первого дня следующей недели. Я не могу понять, почему.

Уроки приходят из java.util.*,

Изменить: Просто зарегистрируйте результат этой функции сегодня (28.05.2018), и вы увидите либо 27.05.2018, либо 03.06.2018. Устройства имеют одинаковые локали и одинаковые часовые пояса.

2 ответа

Решение

Если я правильно понимаю, вы хотите считать воскресенье первым днем ​​недели (как в США).

    WeekFields wf = WeekFields.SUNDAY_START;
    LocalDate today = LocalDate.now(ZoneId.of("Europe/Warsaw"));
    LocalDate firstDayOfThisWeek = today.with(wf.dayOfWeek(), 1);
    System.out.println(firstDayOfThisWeek);

Я пишу код Java и доверяю вам преобразовать в Kotlin. Запуск сегодня (вторник, 29 мая) это напечатано

2018-05-27

Если вместо этого вы хотите, чтобы понедельник был первым днем ​​недели (как в Польше и согласно международному стандарту), просто используйте WeekFields.ISO вместо WeekFields.SUNDAY_START, Если вы хотите, чтобы это зависело от локали, используйте, например, WeekFields.of(Locale.forLanguageTag("pl-PL")),

Еще один и, возможно, более понятный вариант:

    LocalDate firstDayOfThisWeek = today
            .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

В обоих случаях я использую java.time, современный Java API даты и времени. Я думаю, что это хороший пример того, где он обеспечивает более четкий код, что часто имеет место по сравнению со старыми классами даты и времени, такими как Calendar,

Что пошло не так в вашем коде?

Как я понимаю документация, ваш код должен давать воскресенье текущей недели. Calendar использует 1 для воскресенья. Вы могли бы использовать calendar.set(DAY_OF_WEEK, SUNDAY) получить точно так же. Когда я запускаю его сегодня, я получаю 27 мая при использовании воскресенья в качестве первого дня недели и 3 июня при использовании понедельника в качестве первого дня (что означает, что воскресенье - последний день недели). Документация не очень ясна, и Calendar класс может сбивать с толку. В любом случае, вероятно, именно это и произошло, когда вы попробовали на разных устройствах: у них были разные определения недель. Это может быть возможно, даже если они имеют одинаковую локаль, если вы можете настроить определения недели отдельно.

Вопрос: Могу ли я использовать 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 с подпакетами.

связи

Первый день недели отличается для разных стран. Если вы хотите, чтобы оно было одинаковым для всех пользователей, вы можете передать Locale к Calendar,

Calendar currentCalendar = Calendar.getInstance(new Locale("en","UK"));

также из этого ответа вы можете использовать метод setFirstDayOfWeek(), чтобы установить первый день недели. Метод может влиять только на возвращаемые значения WEEK_OF_MONTH или WEEK_OF_YEAR. Для DAY_OF_WEEK это ничего не делает.

Вы можете реализовать что-то вроде:

Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
int rec = cal.get(Calendar.WEEK_OF_MONTH);
System.out.println(rec);

Подробнее об API ЗДЕСЬ

Другие вопросы по тегам