如果天数包括另一年的天数,我如何获得剩余天数?

How do I get a number of days left if the number of days includes the days of another year?

我正在尝试实现一些可以倒计时事件发生前剩余天数的东西。虽然处理同一年内的日子很好。但是现在我在显示一些天数时遇到了问题,其中包括不在当年的天数。例如,如果我输入目标日期为 2020 年 1 月 1 日,当前日期为 2019 年 9 月 30 日。它将 return -272(天),这通常没有任何意义。

我尝试过在线理解和使用代码,但 none 对我有用。

下面的代码所做的是 return 剩下的天数,但仅当这些天数在同一年内时才有效。 labeledDate 变量是输入字符串 (dateStamp) 的一部分,它仅显示格式为 "dd MMMM yyyy".

的日期
// Show how many days left before event occurs
        try {
            String labeledDate = viewHolder.dateStamp.getText().toString().substring(5);

            Calendar currentDay = Calendar.getInstance();
            final Calendar targetDay = Calendar.getInstance();

            SimpleDateFormat ourDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.getDefault());
            targetDay.setTime(ourDateFormat.parse(labeledDate));

            if (targetDay.compareTo(currentDay) > 0) {

                int daysLeft = targetDay.get(Calendar.DAY_OF_YEAR) - currentDay.get(Calendar.DAY_OF_YEAR);

                if (daysLeft == 1) {
                    viewHolder.dayCounter.setText("Tomorrow");
                }
                else {
                    viewHolder.dayCounter.setText(daysLeft + " days");
                }
            }
            else if (targetDay.compareTo(currentDay) == 0) {
                viewHolder.dayCounter.setText("Today");
            }
            else {
                viewHolder.dayCounter.setText("Expired");
            }
        } catch (ParseException e) {
            Log.d("PARSE EXCEPTION", e.getMessage());
        }

根据我目前的理解,Calendar.DAY_OF_YEAR是(大概)365天。如果我输入 2020 年 1 月 1 日这个日期,它不会听年份,而只会关注日期和月份。因此,如果我将目标日期输入为 2020 年 1 月 1 日,将当前日期输入为 2019 年 9 月 30 日,那么它将 return -272(天)从 1 月 1 日减去 9 月 30 日(忽略年数)。

我想要的是,如果我输入上面的输入,那么它将 return 93 天而不是 -272 天。任何可以帮助我实现这一目标的东西都会受到赞赏。

您的逻辑适用于同一年,只是因为 calendar.get(Calendar.DAY_OF_YEAR) returns 天从 1 月 1 日到该年的给定日期。因此,在同一年的情况下,目标日期和当前日期按预期工作。让我们通过一个例子来探索它

targetCalendar.set(2019, 11, 31);

System.out.println(currentCalendar.get(java.util.Calendar.DAY_OF_YEAR)); // Day of year since 1 Jan 2019, which is 273
System.out.println(targetCalendar.get(java.util.Calendar.DAY_OF_YEAR));  // Day of year since 1 Jan 2019, which is 365
// So your logic as per question works fine, gives 92 days (365 - 273) as result for below
System.out.println(targetCalendar.get(java.util.Calendar.DAY_OF_YEAR) - currentCalendar.get(java.util.Calendar.DAY_OF_YEAR));


// No lets change date for targetCalendar into next year
targetCalendar.set(2020, 0, 1);

System.out.println(currentCalendar.get(java.util.Calendar.DAY_OF_YEAR)); // Day of year since 1 Jan 2019, which is 273
System.out.println(targetCalendar.get(java.util.Calendar.DAY_OF_YEAR));  // Day of year since 1 Jan 2020, which is 1
// So your logic as per question works fine, gives -272 days (1 - 273) as result for below
System.out.println(targetCalendar.get(java.util.Calendar.DAY_OF_YEAR) - currentCalendar.get(java.util.Calendar.DAY_OF_YEAR));

希望你的逻辑有问题。


你可以通过这样的方式得到结果

long msDiff = targetDay.getTimeInMillis() - currentDay.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);

这就是我总是得到天差的方法:

String cDate = "09/30/2019";
String fDate = "09/30/2020";
SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date currentDate = df.parse(cDate);
Date futureDate = df.parse(fDate);

long diffMill = Math.abs(currentDate.getTime() - futureDate.getTime());
long diff = TimeUnit.DAYS.convert(diffMill, TimeUnit.MILLISECONDS);

java.time 和 ThreeTenABP

有了java.time,现代的Java日期和时间API,就更简单了:

    DateTimeFormatter dateFormatter
            = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.ENGLISH);

    String labeledDate = "01 January 2020";
    LocalDate currentDay = LocalDate.now(ZoneId.of("America/Louisville"));
    try {
        LocalDate targetDay = LocalDate.parse(labeledDate, dateFormatter);
        long daysLeft = ChronoUnit.DAYS.between(currentDay, targetDay);
        if (daysLeft < 0) {
            System.out.println("Expired");
        } else if (daysLeft == 0) {
            System.out.println("Today");
        } else if (daysLeft == 1) {
            System.out.println("Tomorrow");
        } else {
            System.out.println("" + daysLeft + " days");
        }
    } catch (DateTimeParseException dtpe) {
        System.out.println("Parse exception: " + dtpe.getMessage());
    }

当我运行刚才这个代码片段时,输出是:

92 days

如果不是 America/Louisville,请替换为您想要的时区。因为地球上所有地方的日期都不同。

如果您不想让 if-else 结构基于剩余的天数,您也可以使用 isEqualisBefore and/or isAfter LocalDate.

的方法

但是不是需要AndroidAPI26级吗?

它不需要 API 级别 26。java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 和更新的 Android 设备上(从 API 级别 26)内置现代 API。
  • 在 Java 6 和 7 中获取现代 类 的 ThreeTen Backport(ThreeTen 用于 JSR 310;请参阅底部的链接)。
  • 在(较旧的)Android 使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 类。

链接