为什么Calendar before()方法在相同日期返回true

时间:2016-02-19 16:48:27

标签: java date calendar

我根据dueDate字段与当前日期的比较方式设置颜色字段。 dueDate是SQL日期类型。我的问题是当我传递当前日期时Calendar.before()方法说日期在当前日期之前。我的代码是:

private String getDateDueColor(Date dateDue) {
      Calendar today =  Calendar.getInstance();
      today.setTime(new java.sql.Date(Calendar.getInstance().getTime().getTime()));
      Calendar dueDate = Calendar.getInstance();
      dueDate.setTime(dateDue);
      if(dueDate.before(today)){
        return RED;
      }else{
        return NORMAL;
      }
  }

我设置了一个断点并比较了dueDatetoday,并且每个对象的cdate字段中的所有信息看起来都相同,但dueDate.before(today)仍然返回true 。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:4)

你确定他们是平等的吗? equalsDate的方法Calendar表示它们表示相同的时间值(距离Epoch的毫秒偏移量)。请参阅javadocs for Calendar.equals method

  

将此Calendar与指定的Object进行比较。当且仅当参数是同一日历系统的Calendar对象时,结果才为真,该对象在与此对象相同的Calendar参数下表示与Epoch相同的时间值(毫秒偏移)

compareTo compareTo用于确定日历实例是否在另一个之前。同样,clear使用的是毫秒精度。来自before method docs states

  

比较两个Calendar对象所代表的时间值(与Epoch的毫秒偏移量)

替代方案是:

  1. 如果您必须使用日历,请创建新实例,对其使用{{1}}方法,然后使用the docs设置值(年,月,小时,分钟,秒)。
  2. 使用新的set method并选择一种更能代表您想要的类型(可能是java.time API
  3. 如果您不能使用Java 8,请使用java.time.LocalDate

答案 1 :(得分:1)

answer by marcospereira是正确的。我将添加一些关于修改问题中显示的代码的一般性建议,并展示java.time的使用。

仅将java.sql用于数据库传输

不要传递java.sql类型并对它们执行业务逻辑。仅使用java.sql将数据传入和传出数据库。对于java.sql.Timestamp / .Date /。时间立即将它们转换为java.time对象。然后继续您的业务逻辑。

LocalDate due = myJavaSqlDate.toLocalDate();

避免旧的日期时间类

避免使用与最早版本的Java捆绑在一起的旧日期时间类,例如java.util.Date/.Calendar。它们令人困惑,设计糟糕,麻烦。

java.time

在Java 8及更高版本中,旧的日期时间类已被java.time框架取代。这些新类是巨大的改进。灵感来自Joda-Time,由JSR 310定义,并由ThreeTen-Extra项目扩展。

仅限日期值

问题中的代码表明您希望使用java.sql.Date之类的仅限日期的值。然而,您将其与java.util.Calendar混合,后者代表日期一个时间。

在本答案的上方,您可以java.time.LocalDate课程。此类表示仅包含日期的值,没有时间或时区。

时区

在处理仅限日期的值时,时区至关重要。仅限日期(没有时间)本质上是模棱两可的。在任何特定时刻,世界各地的日期都不一样。新的一天在东部早些时候开始。巴黎午夜过后几分钟仍在蒙特利尔“昨天”。

因此,确定“今天”需要一个时区。如果未指定,则隐式应用JVM的当前默认时区。不好。结果可能在运行时有所不同,具体取决于主机操作系统和JVM的设置。在运行期间,甚至可以通过JVM中任何应用程序的任何线程中的任何代码更改默认时区。

因此,最好明确指定所需/预期的时区。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );

现在进行比较以查看截止日期是否已过去。

if( today.isAfter( due ) ) {
    // Overdue.
}

答案 2 :(得分:0)

另一种方法是比较yyyy,mm,dd字段。如果它们是相同的 - 不要使用.after()和.before() 西蒙弗兰兹