Преобразование набора календарей DAY_OF_WEEK для использования TemporalAdjusters

У меня есть такой устаревший код

        final Calendar cal = new GregorianCalendar();
        cal.setTime(today);
        // changed on May-03-2004
        //cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            cal.add(Calendar.DAY_OF_YEAR, -6);
        } else {
            cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        }
        //System.out.println("Begin of cycle: " + cal.getTime());

И я хотел бы преобразовать его для использования класса java.time TemporalAdjuster, чтобы, надеюсь, сделать его более читабельным.

Но я не совсем уверен, как интерпретировать https://stackoverflow.com/a/1319484/242042, чтобы поведение соответствие.


person Archimedes Trajano    schedule 01.02.2020    source источник


Ответы (3)


Предполагая, что today действительно является сегодняшней датой, тогда версия API времени Java, используя TemporalAdjusters будет выглядеть так:

LocalDate today = LocalDate.now();

TemporalAdjuster adjuster = TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY);
LocalDate monday = today.with(adjuster);

System.out.println(today + " -> " + monday);

Пример вывода

2020-02-01 -> 2020-01-27

2020-02-01 — это суббота, а 2020-01-27 — предыдущий понедельник.

person Andreas    schedule 02.02.2020

DayOfWeek реализует TemporalAdjuster

Я думаю, что ваш код пытается установить объект Calendar в понедельник той же недели ISO, то есть в понедельник, предшествующий сегодняшнему дню, если сегодня еще не понедельник (хотя это не всегда будет результатом во всех локалях). Это очень просто, когда знаешь как.

    LocalDate today = LocalDate.of(2020, Month.FEBRUARY, 2);
    LocalDate monday = today.with(DayOfWeek.MONDAY);
    System.out.println("Monday of the same week is " + monday + ", a " + monday.getDayOfWeek());

Вывод из этого фрагмента:

Понедельник той же недели 2020-01-27, ПОНЕДЕЛЬНИК

LocalDate всегда использует календарь ISO, в котором понедельник является первым днем ​​недели, поэтому today.with(DayOfWeek.MONDAY) дает вам понедельник той же недели, другими словами, предыдущий понедельник сегодняшнего дня еще не является понедельником. GregorianCalendar использовал определение недели для локали по умолчанию, что немного усложнило код, чтобы убедиться, что он будет корректно работать в локалях, где воскресенье — первый день недели. LocalDate ведет себя одинаково во всех локалях, что является одной из причин, почему код, использующий LocalDate, проще.

person Ole V.V.    schedule 02.02.2020

Хорошо, поигравшись и попробовав разные комбинации в https://repl.it/@trajano/setCal

Код переводится как

  public static LocalDate doIt(LocalDate todayDate) {
    final LocalDate c2;
    if (todayDate.getDayOfWeek() == DayOfWeek.SUNDAY) {
      c2 = todayDate.minusDays(6);
    } else {
      c2 = todayDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }
    return c2;

  }
person Archimedes Trajano    schedule 01.02.2020
comment
Зачем нужно заявление if? Разве with(previousOrSame(MONDAY)) не сделает то же самое, что и minusDays(6) в воскресенье? - person Andreas; 02.02.2020
comment
но похоже, что вы правы, я просто попытался прокомментировать это в своем Repl, спасибо, это упрощает ситуацию. - person Archimedes Trajano; 02.02.2020