【问题标题】:How do I get a number of days left if the number of days includes the days of another year? [duplicate]如果天数包括另一年的天数,我如何获得剩余天数? [复制]
【发布时间】:2020-01-29 09:41:39
【问题描述】:

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

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

以下代码的作用是返回剩余天数,但仅当这些天数在同一年内时才有效。标签日期变量是输入字符串 (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 日,那么它将从 1 月 1 日减去 9 月 30 日(忽略年份)返回 -272(天)。

我想要的是,如果我输入上面的输入,那么它将返回 93 天而不是 -272 天。任何可以帮助我实现这一目标的东西都将不胜感激。

【问题讨论】:

  • 顺便考虑扔掉长期过时且臭名昭著的麻烦SimpleDateFormat和朋友,并将ThreeTenABP添加到您的Android项目中,以便使用java.time,现代Java日期和时间API .使用起来感觉好多了。

标签: java android date calendar date-difference


【解决方案1】:

您的逻辑适用于同一年,因为 calendar.get(Calendar.DAY_OF_YEAR) 返回从 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));

希望你的逻辑有问题。


你可以通过like得到结果

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

【讨论】:

    【解决方案2】:

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

    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);
    

    【讨论】:

      【解决方案3】:

      java.time 和 ThreeTenABP

      使用现代 Java 日期和时间 API java.time,它更简单:

          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());
          }
      

      刚才我运行这段代码sn-p的时候,输出是:

      92 天

      如果不是美国/路易斯维尔,请替换您想要的时区。因为地球上所有地方的日期都不会相同。

      如果您不想将 if-else 构造基于保留的天数,您还可以使用LocalDateisEqualisBefore 和/或isAfter 方法。

      但它不需要 Android API 级别 26 吗?

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

      • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。
      • 在 Java 6 和 7 中获得 ThreeTen Backport,这是现代类的后向端口(JSR 310 的 ThreeTen;请参阅底部的链接)。
      • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

      链接

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-18
        • 2013-06-26
        • 2014-06-11
        • 1970-01-01
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多