【问题标题】:Why Calendar.after always retun true?为什么 Calendar.after 总是返回 true?
【发布时间】:2020-01-29 11:40:54
【问题描述】:

您好,谁能解释一下为什么 Calendar .after 方法会出现这种异常行为

Calendar cal = Calendar.getInstance();
Calendar cal1 = Calendar.getInstance();

cal.set(Calendar.HOUR, 14);
cal1.set(Calendar.HOUR, 13);

System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());      

cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());

输出:

true Cal Tue Oct 01 02:55:16 IST 2019 cal1 Tue Oct 01 01:55:16 IST 2019
true Cal Wed Oct 30 02:55:16 IST 2019 cal1 Tue Oct 01 01:55:16 IST 2019

但即使我将 cal1 的日期设置为当前日期,我也不明白为什么 cal 在 cal1 之后,

所以如果 cal 是今天,我将时间指定为 14 小时,然后将日期设置为 cal 中的当前日期,而对于 cal1 我没有。

那么为什么 cal.after(cal1) 在第二个 syso 中仍然显示为 true 而我的 cal1 显然比 cal 大 1 天?

【问题讨论】:

  • 解决此类问题的任何建议。
  • 我没有收到您的问题。 1) 02:55h 01:55h 之后。 2) 10 月 30 日是 10 月 1 日之后。所以两个输出都是正确的!不清楚...
  • 您希望从该代码中得到什么其他结果?为什么?
  • 我建议你不要使用Calendar。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time APIZonedDateTime

标签: java date calendar java.util.calendar


【解决方案1】:

有解决此类问题的建议吗?使用 java.time

我同意您的观点,您的代码中有一些令人惊讶的地方。您可能已经打算这样做了:

    ZoneId zone = ZoneId.of("Asia/Kolkata");
    ZonedDateTime zdt = ZonedDateTime.now(zone);
    ZonedDateTime zdt1 = ZonedDateTime.now(zone);

    zdt = zdt.withHour(14);
    zdt1 = zdt1.withHour(13);

    System.out.println(zdt.isAfter(zdt1) + " zdt " + zdt + " zdt1 " + zdt1);

    zdt = zdt.withDayOfMonth(ZonedDateTime.now(zone).getDayOfMonth());
    System.out.println(zdt.isAfter(zdt1) + " zdt " + zdt + " zdt1 " + zdt1);

我刚才运行代码时的输出:

true zdt 2019-09-30T14:44:13.630029+05:30[Asia/Kolkata] zdt1 2019-09-30T13:44:13.630362+05:30[Asia/Kolkata]
true zdt 2019-09-30T14:44:13.630029+05:30[Asia/Kolkata] zdt1 2019-09-30T13:44:13.630362+05:30[Asia/Kolkata]

我两次都得到true,就像你从代码中得到的一样,这不足为奇。正如其他人所说,02:55h 在 01:55h 之后,10 月 30 日在 Oct 01 之后。另外,参考我的结果,14:44 在 13:44 之后。在这两行中,这两个时间都进行了比较。

我正在使用 java.time,这是现代 Java 日期和时间 API。

你的代码出了什么问题?

您的代码中的惊喜源于 Calendar 类的设计不佳,并且其行为通常与我们立即预期的不同。

  1. 为什么当您将小时设置为 14 时,您会得到 Tue Oct 01 02:55:16 IST 2019?日期已更改为下个月,一天中的小时是 2,而不是 14。
  2. 为什么当您将日期设置为今天的 9 月 30 日时,您会得到 10 月 30 日?

对于 1.,Calendar.HOUR 指的是上午或下午从 0 到 11 的小时。因此,将其设置为 14 我们应该预料到会出现异常。具有标准设置的Calendar 不在乎。由于时间已经在下午,因此推断,因此下午 14 点变为第二天凌晨 2 点。由于今天是 9 月的最后一天,因此您得到的是 10 月 1 日。

对于 2.,Calendar.DATE 不是指完整日期,而是指月份中的某一天。由于当前日期是 30 日,并且我们已经有 10 月 1 日,所以我们得到 10 月 30 日。

长话短说:避免使用Calendar 类。使用 ZonedDateTime 和/或其他类形成 java.time,现代 Java 日期和时间 API。与他们一起工作的感觉要好得多,并且像您经历过的那样给您带来的惊喜要少得多。

链接

Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

    【解决方案2】:

    Java 文档 - Calendar.after()

    public boolean after(Object when) {
        return when instanceof Calendar && compareTo((Calendar)when) > 0;
    }
    
            //By definition :- true if the time of this Calendar is after the time represented by when; false otherwise.
    
            System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
            //true Cal Tue Oct 01 02:17:46 IST 2019 cal1 Tue Oct 01 01:17:46 IST 2019
    
            cal.set(Calendar.HOUR, 13);
            cal1.set(Calendar.HOUR, 14);
    
            System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
            //false Cal Tue Oct 01 01:16:55 IST 2019 cal1 Tue Oct 01 02:16:55 IST 2019
    
            cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
            System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
            //true Cal Wed Oct 30 13:17:46 IST 2019 cal1 Tue Oct 01 14:17:46 IST 2019
    

    【讨论】:

    • 对不起,你弄错了,我不想更改 Cal,因为它来自某个字符串的特定时间,例如解析为 14:00:00,并且 cal1 必须比较是否它大于或小于 cal,例如问问题
    • 所以如果我做 cal.set(Calendar.HOUR, 14); cal1.set(Calendar.HOUR, 13); cal1.add(日历.DATE, 1);当我的 cal1 比 cal 提前将近 2 天时, cal.after(cal1) 仍然会给出 true
    • cal1 不大于 cal。 cal 是 30 oc​​t,但 cal1 是 1 oct。逻辑上是真的。明白了吗?
    【解决方案3】:
             System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime()); 
            //true Cal Tue Oct 01 02:25:19 MMT 2019 cal1 Tue Oct 01 01:25:19 MMT 2019  
        cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
        System.out.println(cal1.after(cal)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
       //false Cal Wed Oct 30 02:25:19 MMT 2019 cal1 Tue Oct 01 01:25:19 MMT 2019
    

    【讨论】:

    • 但是 cal1.after(cal) 是我所期待的,因为如果我们看到 cal1 的日期比 cal 大,那么为什么 cal.after(cal1) 会给出 true
    • 这是仅根据时间比较还是还检查日期
    • 返回:如果此日历的时间在when表示的时间之后,则返回true;否则为假。
    • cal---->>WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=274,DAY_OF_WEEK=3; cal1----->WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=303,DAY_OF_WEEK=4
    【解决方案4】:

    使用

    cal.setTime((Calendar.getInstance()).getTime());
    

    而不是

    cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
    

    给出想要的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-03
      • 2021-09-11
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多