Нужно запросить экземпляр календаря для настройки календаря для работы - PullRequest
0 голосов
/ 24 февраля 2019

У меня есть экземпляр Calendar, который начинается с первого дня декабря.Я пытаюсь установить для этого экземпляра Календаря последний вторник года.Где-то между установкой последнего дня года и дня недели экземпляр Calendar возвращается к исходному времени:

Calendar cal = ....;
Log.d(TAG, String.format("Starting here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));

cal.set(Calendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));
cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);

Log.d(TAG, String.format("Ending here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
/* Other stuff */

Дает мне эти выходные данные за 2017 и 2018 годы:

2017:

Starting here 2017-12-1 
Ending here 2017-11-28 

2018:

Starting here 2018-12-1 
Ending here 2018-11-27 

Неудовлетворительное исправление

Однако, если я получаю данные из экземпляра Календаря, он работает нормально:

Calendar cal = ....;
Log.d(TAG, String.format("Starting here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));

cal.set(Calendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));

// Ask the Calendar instance for information
long dummyValue = cal.getTimeInMillis();

cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);

Log.d(TAG, String.format("Ending here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
/* Other stuff */

Дает мне этот вывод на 2017 и 2018 годы:

2017:

Starting here 2017-12-1 
Ending here 2018-1-2 

2018:

Starting here 2018-12-1
Ending here 2019-1-1 

И да, я знаю датыВторой набор значений не последний вторник.Вот для чего /* Other stuff */.

1 Ответ

0 голосов
/ 25 февраля 2019

java.time и ThreeTenABP

    LocalDate myLocalDate = LocalDate.of(2017, Month.DECEMBER, 1);

    System.out.format("Starting here: %s%n", myLocalDate);
    LocalDate lastTuesdayOfYear = myLocalDate
            .with(TemporalAdjusters.lastDayOfYear())
            .with(TemporalAdjusters.previousOrSame(DayOfWeek.TUESDAY));
    System.out.format("Ending here:   %s%n", lastTuesdayOfYear);

Вывод на 2017 год:

Starting here: 2017-12-01
Ending here:   2017-12-26

Для 2018 года:

Starting here: 2018-12-01
Ending here:   2018-12-25

Это означает , что дает вам последний вторник года.Для этого больше ничего не нужно.

Вопрос: Могу ли я использовать java.time на Android?

Да, java.time прекрасно работает на старых и новых устройствах Android.Для этого требуется как минимум Java 6 .

  • В Java 8 и более поздних версиях и на более новых устройствах Android (от уровня API 26) современный API поставляется встроенным.
  • В Java 6 и 7 получают ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. Ссылки внизу).
  • На (более старых) Android используется версия ThreeTen для AndroidBackport.Это называется ThreeTenABP.И убедитесь, что вы импортируете классы даты и времени из org.threeten.bp с подпакетами.

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

Класс Calendar просто сбивает с толку.В вашем случае это ведет себя в соответствии с документацией.Позвольте мне процитировать:

Разрешение полей календаря

При вычислении даты и времени из полей календаря ... может быть противоречивая информация (например, вторник15 июля 1996 г. (григорианский) - 15 июля 1996 г. фактически понедельник).Calendar разрешит значения полей календаря для определения даты и времени следующим образом.

В случае какого-либо конфликта в значениях полей календаря, Calendar отдает приоритеты полям календаря, которые были установлены позднее.Ниже приведены комбинации полей календаря по умолчанию.Будет использоваться самая последняя комбинация, определяемая самым последним установленным одиночным полем.

Для полей даты:

 YEAR + MONTH + DAY_OF_MONTH
 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 YEAR + DAY_OF_YEAR
 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR

Inваш случай DAY_OF_WEEK был установлен совсем недавно.DAY_OF_WEEK в трех из пяти комбинаций выше.Какой он выбирает, я не знаю.Ни одно из них также не включает DAY_OF_YEAR, другое поле, которое вы устанавливаете, поэтому DAY_OF_YEAR не используется.Что объясняет поведение, которое вы видели.Если вы настаиваете на использовании Calendar, вы должны быть в состоянии получить где-то с cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);, поскольку отрицательные значения отсчитываются в обратном направлении с конца месяца.

Однако Calendar не только плохо и запутанно разработанЭто тоже давно устарело.Поэтому попробуйте вместо этого использовать java.time.

Ссылки

...