Получите правильную разницу между двумя выбранными датами в годах, месяцах и днях в Android - PullRequest
0 голосов
/ 25 апреля 2020

Как я могу получить разницу между двумя выбранными датами из календаря в Android в днях, месяцах и годах? Мы знаем все, что месяцы иногда имеют 30 дней, а иногда 31 день, а в феврале 28 дней - каждые 4 года - 29 дней. Я хочу получить результат, например, такой: 2 года и 6 месяцев и 24 дня. Я пытаюсь использовать LocalDate, так что это мой код:

public void onSelectedDayChange(@NonNull CalendarView view,
        final int year, final int month, final int dayOfMonth) {

    textView.setText(String.valueOf(dateDiff(year,month,dayOfMonth)));
}

public Period dateDiff(int year,int month,int day){
    final int Day = c.get(Calendar.DAY_OF_MONTH);
    final int Month = c.get(Calendar.MONTH);
    final int Year = c.get(Calendar.YEAR);
    LocalDate localDate1 = LocalDate.of(year,month,day);
    LocalDate localDate2 = LocalDate.of(Year,Month,Day);

    Period period = Period.between(localDate2,localDate1);

    return period;
}

Я проверил код, но получил неверный результат. Когда я проверил это с днями (05/05/2020), я получил 8 дней, но разница составляет 7 дней, потому что у "апреля" есть 30 дней, и для выбранного дня (02/07/2020) я получил 2 месяца и 8 дней или правильный ответ 2 месяца и 7 дней. Сначала я пытаюсь получить правильный результат, если есть функция или формула расчета для решения этого неправильного результата, это поможет мне.

Наконец, я получаю в результате каждый раз что-то вроде (P2M8D), что означает 2 месяцы и 8 дней, или, например, (P7D), что означает 7 дней, так как я могу изменить этот текст на понятный, как 2 месяца и 8 дней или 7 дней, как 2 примера, потому что я нашел проблему в результате, потому что мы смешали между цифрами и символами.

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Вы на правильном пути.

  1. Следуйте Java соглашениям об именах. Имя переменной или параметра начинается со строчной буквы. Всегда. Особенно странно, что у вас есть параметр year и переменная Year. Это может привести к ошибкам в какой-то момент (хотя в данный момент это не является причиной).
  2. Так как вы можете использовать LocalDate и Period с java .time, современный Java API даты и времени, не смешивайтесь с плохо разработанным и устаревшим Calendar классом, он просто усложняет ситуацию. Ваше использование LocalDate и Period в основном правильно. Для получения текущей даты в виде LocalDate используйте LocalDate.now(ZoneId.systemDefault()) (и нам больше не нужны переменные в верхнем регистре, две проблемы решаются одним выстрелом).
  3. Я не знаю вашего средства выбора даты, но я подозреваю, что оно может использовать цифры месяца на основе 0: 0 для января по 11 для декабря. Если это так, вам нужно добавить 1 к номеру месяца при создании объекта LocalDate.

Для более удобочитаемого текста используйте методы объекта Period, чтобы получить числа и собрать ваша собственная строка. Простой пример:

        String periodText = "" + period.getYears() + " years "
                    + period.getMonths() + " months " + period.getDays() + " days";

Вы захотите изменить его так, чтобы пропустить годы, если они равны 0, и месяцы, если они равны 0. Посмотрите, какой текст вы хотите написать, если все числа равны 0 Вы захотите что-то написать, иначе пользователь будет сбит с толку. Еще одним возможным уточнением будет использование единственного числа слов, если оно точно равно 1 (1 year, а не 1 years и т. Д. 1050 *.). Вы можете изучить использование StringJoiner и написать вспомогательный метод, который возвращает строку с номером и правильной формой существительного, например 1 month, но 2 months.

Редактировать : Код для форматирования периода

Изложив мое предложение в коде, вот способ отформатировать ваш Period:

    StringJoiner joiner = new StringJoiner(" ");
    joiner.setEmptyValue("No time at all");
    if (period.getYears() != 0) {
        joiner.add(singularOrPlural(period.getYears(), "year", "years"));
    }
    if (period.getMonths() != 0) {
        joiner.add(singularOrPlural(period.getMonths(), "month", "months"));
    }
    if (period.getDays() != 0) {
        joiner.add(singularOrPlural(period.getDays(), "day", "days"));
    }
    String periodText = joiner.toString();

    System.out.println(periodText);

Код использует этот вспомогательный метод:

private static String singularOrPlural(int count, String singular, String plural) {
    if (count == -1 || count == 1) {
        return "" + count + ' ' + singular;
    } else {
        return "" + count + ' ' + plural;
    }
}

Пример выходных данных:

No time at all
1 day
2 days
1 month
1 month 1 day
2 months
3 years 4 months 5 days
-1 year -1 month -6 days
0 голосов
/ 25 апреля 2020

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

Кстати, вы можете попробовать это преобразовать формат как P2M8D до 2 месяцев и 8 дней:

public static void main(String[] args) {
    int year = 2020, month = 7, day = 2;
    int yearDiff = dateDiff(year, month, day).getYears();
    int monthDiff = dateDiff(year, month, day).getMonths();
    int dayDiff = dateDiff(year, month, day).getDays();
    System.out.println("Period -> yyyy:" + yearDiff + " mm:" + monthDiff + " dd:" + dayDiff); // OUTPUT: Period -> yyyy:0 mm:3 dd:7
}


static Period dateDiff(int year, int month, int day) {
    Calendar c = Calendar.getInstance();
    final int Day = c.get(Calendar.DAY_OF_MONTH);
    final int Month = c.get(Calendar.MONTH);
    final int Year = c.get(Calendar.YEAR);
    LocalDate localDate1 = LocalDate.of(year, month, day);
    LocalDate localDate2 = LocalDate.of(Year, Month, Day);

    return Period.between(localDate2, localDate1);
}

Вы должны использовать getDays , getMonths и getYears методы.

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