2016-02-19 146 views
0

我正在根据dueDate字段与当前日期的比较来设置颜色字段。 dueDate是SQL日期类型。我的问题是,当我通过当前日期Calendar.before()方法表示日期在当前日期之前。我的代码是:为什么Calendar()方法在相同日期返回true

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。任何帮助,将不胜感激!

+0

dateDue的值是什么 – SDS

+3

'Calendar.getInstance().getTime()。getTime()'是一个不必要的冗长和神秘的做'System.currentTimeMillis()'的方法。 – VGR

+0

我在StackOverflow文章中发现了Calendar.getInstance()。getTime()。getTime()。感谢更短的版本。 – ponder275

回答

4

你确定他们是平等的吗?方法equals对于DateCalendar意味着它们表示相同的时间值(与Epoch的毫秒偏移量)。请参阅javadocs for Calendar.equals method

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

before method docs states 用于决定日历实例是否在另一个之前。再次,compareTo正在使用毫秒精度。从the docs

比较时间值(从历元毫秒偏移量)由两个日历对象表示。

的替代方案是:

  1. 如果你必须使用日历,创建新实例,对他们使用clear方法,然后使用set method设定值(年,月,HOUROFDAY,分,秒) 。
  2. 使用新java.time API,选择某种类型更好地代表了你想要的东西(也许java.time.LocalDate
  3. 使用Joda Time如果你不能去到Java 8
+0

感谢您的信息! – ponder275

+0

为了我的目的,我只需要设置日,月和年。清除Calendar实例后,如何知道将字段设置为的内容。我是否使用带有未清除日历实例的get方法? – ponder275

1

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

使用java.sql中只对数据库传输

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

LocalDate due = myJavaSqlDate.toLocalDate(); 

避免旧日期,时间类

避免与最早版本的Java,如java.util.Date/.Calendar捆绑旧日期时间类。他们混乱,设计不好,麻烦。

java.time

在Java 8和更高版本,旧的日期时类已被java.time框架所取代。这些新课程是一个巨大的改进。受JSR 310定义的Joda-Time的启发,并由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. 
} 
+0

你是对的我只需要仅限日期的信息,但我还需要在日期的另一部分中更改日期15天,这就是为什么我使用Calendar类的原因。我们的项目使用Java 7,所以我不能使用新的框架。我可以问,看看我们是否可以包括Joda-Time。这段代码永远不会跨时区使用,所以我仍然需要担心显式声明时区? – ponder275

+0

要更改日期,请调用'plusDays'或'minusDays'方法:'today.plusDays(15)'。至于指定时区,是的总是明确指定。如果系统管理员在主机操作系统上更改时区,或者在启动JVM的命令行上指定开关,则软件会出现错误的日期。尝试调试时,这是一个*可怕的问题。如果您希望时区为“America/LosAngeles”或“Europe/Paris”或“Asia/Kolkata”,请说出来。保持不变并全面使用它。至于Joda-Time,是的,如果在Java 8之前肯定会使用它;具有相同的LocalDate和时区类。 –

+1

@ ponder275 **更新:** Joda-Time项目现在处于维护模式。该项目建议迁移到java.time类。对于Java 6和7,使用* ThreeTen-Backport *项目而不是Joda-Time。对于较早的Android,请参阅* ThreeTenABP *项目。 –

0

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

相关问题