Получить следующий день рождения из списков дат - PullRequest
0 голосов
/ 01 июля 2019

У меня проблема с вычислением даты. Здесь моя ситуация; У меня есть список дат дня рождения, например:

List<Date> birthdays = getAllBirthdays(); //getAllBirthdays() returns full list of dates

и хочу теперь рассчитать следующие три дня рождения. Я много читал о датах, а также реализовал joda time в своем проекте, поэтому я также пытался вычислять с помощью объектов DateTime, но не смог найти хорошее решение, которое сработало. Кто-нибудь может мне помочь с базовой структурой или еще?

Ответы [ 3 ]

1 голос
/ 01 июля 2019

Ваш вопрос не совсем понятен.Но я сделаю это.

java.time

Проект Joda-Time сейчас находится в режиме обслуживания.Его создатель и лидер, Стивен Колебурн, продолжал возглавлять JSR 310 и его реализацию java.time , встроенную в Java 8 и более поздние версии.

MonthDay

Похоже, ваш список ежегодных дней рождения должен содержать объекты класса MonthDay.Этот класс представляет месяц и день месяца без года и без часового пояса.

List< MonthDay > birthdays = new ArrayList<>() ;
birthdays.add( MonthDay.of( Month.MARCH , 27 ) ) ;
birthdays.add( MonthDay.of( Month.DECEMBER , 13 ) ) ;

Получить текущий месяц.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
MonthDay mdCurrent = MonthDay.now( z ) ;

Цикл списка.Сравните каждый MonthDay с нашим текущим месяцем md.

if( md.isAfter( mdCurrent ) ) {
    …
}

Если после, примените номер текущего года для генерации LocalDate.

if( md.isAfter( mdCurrent ) ) {
    int y = Year.now( z ).getValue() ;
    LocalDate ld = md.atYear( y ) ;
}
0 голосов
/ 01 июля 2019

Определите пользовательский компаратор, который сравнивает ваши даты в зависимости от того, сколько времени осталось до этого дня рождения, принимая во внимание, что это может быть в этом или следующем году. Сортировка с использованием компаратора. Возьмите первые три элемента отсортированного списка. Удачного кодирования. (Я не пишу код для вас и надеюсь, что вы никогда не ожидали от нас.)

Также посмотрите, если вместо Date объектов вы можете заполнить LocalDate или MonthDay объекты в вашем списке. Date несмотря на то, что имя класса не представляет дату, а класс плохо спроектирован и давно устарел. LocalDate и MonthDay - это классы из java.time, современного Java-API даты и времени, с которым гораздо приятнее работать, чем со старыми классами, такими как Date.

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

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

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

Ссылки

0 голосов
/ 01 июля 2019

Существует несколько способов решения этой проблемы.Одним из способов является создание самостоятельно отсортированного индекса месяца и года рождения, чтобы вы могли быстро найти следующие дни рождения для данного дня.

Первое, что вам нужно понять, это то, что «следующие» дни рождения не должныпринять во внимание год.Если вы просто отсортируете или сравните дату, год даст вам недействительные даты.Один из способов обойти это - создать ключ для дня рождения, который однозначно идентифицирует день рождения независимо от года.В частности, вы хотите ключ, который можно заказать в «хронологическом порядке».Например:

  LocalDate d1 = LocalDate.parse("1980-10-31');
  int key1 = d1.getMonthValue() * 100 + d1.getDayOfMonth();

  LocalDate d2 = LocalDate.parse("2001-10-31');
  int key2 = d2.getMonthValue() * 100 + d2.getDayOfMonth();

  key1 == key2

Так что теперь, когда у вас есть способ генерации ключа, вы захотите сгенерировать карту ключей для дней рождения.Вы можете сделать это достаточно легко с помощью сборщика groupingBy.

  Function<LocalDate, Integer> key = (d) -> d.getMonthValue() * 100 + d.getDayOfMonth();
  Map<Integer, List<LocalDate>> lookup = birthdays.stream().collect(Collectors.groupingBy(key));

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

Наконец, вы захотите найти следующие три дня рождения.Один из способов сделать это - отсортировать ключи, найти позицию следующей записи и затем прочитать следующие два.Поскольку это упорядоченный список ключей, мы можем создать индекс ключей, отсортировать его и использовать двоичный поиск, чтобы найти следующую запись.Итак, давайте создадим индекс:

    List<Integer> searchIndex = lookup.keySet().stream().sorted().collect(Collectors.toList());

Итак, теперь мы можем использовать searchIndex, чтобы найти ближайший ключ к ключу для даты ввода.Затем мы можем использовать этот ключ, чтобы найти список дней рождения для этого ключа из lookup.

Мы можем получить следующие две даты, просто взглянув на следующие два ключа в индексе.Обратите внимание, что вы захотите перейти к началу индекса, когда дойдете до конца.Например, если вы будете искать следующие три дня рождения 31 декабря, вам нужно будет продолжить проверку в январе.

        List<LocalDate> birthdays = getAllBirthdays();

        Function<LocalDate, Integer> key = (d) -> d.getMonthValue() * 100 + d.getDayOfMonth();
        Map<Integer, List<LocalDate>> lookup = birthdays.stream().collect(Collectors.groupingBy(key));
        List<Integer> searchIndex = lookup.keySet().stream().sorted().collect(Collectors.toList());
        int index = Collections.binarySearch(searchIndex, key.apply(LocalDate.now()));

        // Find the positive index if the index doesn't contain the current MMdd 
        if (index < 0) {
            index = -index -1;
        }

        for (int i = 0; i < 3; ++i) {
            // Wrap around to the start of the year
            if (index >= searchIndex.size()) {
                index = 0;
            }
            System.out.println(lookup.get(searchIndex.get(index++)));
        }

Я использовал java.util.LocalDate в приведенном выше коде, но вы могли бы каклегко использовать joda's LocalDate.Оба предпочтительнее использовать java.util.Date

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...