[英]Java compareTo Dates cannot be equal
I am trying to compare 2 dates, the first date is from the MySQL database, and the second is from the current date. 我想比较2个日期,第一个日期来自MySQL数据库,第二个日期来自当前日期。
as you can see below, there are different dates in the database 如下所示,数据库中有不同的日期
But the problem is that I got 3 if statements, which should tell my program if the Database date is before, after or equal the current date.
但问题是我得到3个if语句,它应该告诉我的程序数据库日期是在当前日期之前,之后还是等于当前日期。 The Before and After statements should work, but it can see the date 2018-06-12 should be equal to the current date so it ends in the "before statement".
Before和After语句应该有效,但是它可以看到2018-06-12的日期应该等于当前日期,因此它以“before statement”结束。
Hope you can see what I have done wrong. 希望你能看到我做错了什么。
private static void Resetter() throws ParseException, SQLException {
String host = "****";
String username = "root";
String mysqlpassword = "";
//Querys
String query = "select * from accounts";
String queryy = "update accounts set daily_search_count = 0 where id = ?";
Connection con = DriverManager.getConnection(host, username, mysqlpassword);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
dateFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ));
Date currentDate = new Date();
while(rs.next()){
System.out.println(dateFormat.format(currentDate));
if (rs.getDate(5).compareTo(currentDate) > 0) {
// System.out.println("Database-date is after currentDate");
} else if (rs.getDate(5).compareTo(currentDate) < 0) {
// System.out.println("Database-date is before currentDate");
PreparedStatement updatexdd = con.prepareStatement(queryy);
updatexdd.setInt(1, rs.getInt(1));
int updatexdd_done = updatexdd.executeUpdate();
} else if (rs.getDate(5).compareTo(currentDate) == 0) {
// System.out.println("Database-date is equal to currentDate");
} else {
System.out.println("Any other");
}
}
}
ResultSet#getDate
returns a date with the time part removed. ResultSet#getDate
返回删除时间部分的日期。 Instantiating a new Date
object does contain the time, so you'll have to remove it yourself. 实例化一个新的
Date
对象确实包含时间,因此您必须自己删除它。 Eg: 例如:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date currentDate = cal.getTime();
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
Instant instant = myResultSet.getObject( … , Instant.class ) ; // Retrieve a `TIMESTAMP WITH TIME ZONE` value in database as an `Instant` for a date with time-of-day in UTC with a resolution as fine as nanoseconds.
LocalDate ld = instant.atOffset( ZoneOffset.UTC ).toLocalDate() ; // Extract a date-only value without time-of-day and without time zone.
if ( ld.isBefore( today ) ) { … } // Compare `LocalDate` objects.
else if ( ld.isEqual( today ) ) { … }
else if ( ld.isAfter( today ) ) { … }
else { … handle error }
You are using, and misusing, troublesome old date-time classes. 您正在使用并滥用麻烦的旧日期时间类。
As others pointed out: 正如其他人指出:
DATE
type holds only a date without a time-of-day and without a timezone DATE
类型仅包含没有时间和没有时区的日期 java.util.Date
class is misnamed, holding both a date and a time-of-day in UTC . java.util.Date
类名称错误,以UTC格式保存日期和时间。 java.sql.Date
class pretends to hold only a date but actually has a time-of-day because this class inherits from the one above, while the documentation tells us to ignore that fact in our usage. java.sql.Date
类假装只保留一个日期但实际上有一个时间,因为这个类继承了上面的那个,而文档告诉我们在我们的用法中忽略这个事实。 (Yes, this is confusing, and is a bad design, a clumsy hack.) Never use the java.util.Date
, java.util.Calendar
, java.sql.Timestamp
, java.sql.Date
, and related classes. 切勿使用
java.util.Date
, java.util.Calendar
, java.sql.Timestamp
, java.sql.Date
和相关类。 Instead, use only the sane java.time classes. 相反,只使用理智的java.time类。 They lead the industry in clean-design and depth of understanding of date-time handling gleaned from the experience of their predecessor, the Joda-Time project.
他们从其前身Joda-Time项目的经验中获得了清洁设计和对日期时间处理的深入理解,引领行业发展。
For date-only value, stored in SQL-standard database type of DATE
, use java.time.LocalDate
. 对于仅限日期的值,存储在
DATE
SQL标准数据库类型中,请使用java.time.LocalDate
。
LocalDate ld = myResultSet.get( … , LocalDate.class ) ; // Retrieving from database.
myPreparedStatement.setObject( … , ld ) ; // Storing in database.
For a date with time-of-day in UTC value, stored in a SQL-standard database type of TIMESTAMP WITH TIME ZONE
, use java.time.Instant
. 对于具有UTC时间值的日期,存储在SQL标准数据库类型
TIMESTAMP WITH TIME ZONE
,请使用java.time.Instant
。 The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Instant
类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。
Instant instant = myResultSet.get( … , Instant.class ) ; // Retrieving from database.
myPreparedStatement.setObject( … , instant ) ; // Storing in database.
For comparing in Java, use the isEqual
, isBefore
, isAfter
, equals
, or compare
methods. 要在Java中进行比较,请使用
isEqual
, isBefore
, isAfter
, equals
或compare
方法。
Boolean overdue = someLocalDate.isAfter( otherLocalDate ) ;
Time zone is crucial in determining a date and a time-of-day from a moment ( Instant
/ TIMESTAMP WITH TIME ZONE
). 时区对于确定日期和时刻(
Instant
/ TIMESTAMP WITH TIME ZONE
)至关重要。
After retrieving your TIMESTAMP WITH TIME ZONE
value from the database as an Instant
, adjust into the time zone or offset-from-UTC whose wall-clock time you want to use in perceiving a date & time-of-day. 从数据库中检索
TIMESTAMP WITH TIME ZONE
值作为Instant
,调整为时区或UTC的偏移量,您想要使用它的挂钟时间来感知日期和时间。 For a time zone, apply a ZoneId
to get a ZonedDateTime
object. 对于时区,应用
ZoneId
以获取ZonedDateTime
对象。 For an offset-from-UTC, apply a ZoneOffset
to get a OffsetDateTime
object. 对于UTC的偏移量,应用
ZoneOffset
来获取OffsetDateTime
对象。 In either case, extract a date-only value by calling toLocalDate
to get a LocalDate
object. 在任何一种情况下,通过调用
toLocalDate
来获取LocalDate
对象来提取仅日期值。
In your case, you apparently want to perceive the date as UTC. 在您的情况下,您显然希望将日期视为UTC。 So apply the constant,
ZoneOffset.UTC
to get an OffsetDateTime
因此,应用常量
ZoneOffset.UTC
来获取OffsetDateTime
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
LocalDate ld = odt.toLocalDate() ; // Extract a date-only value without time-of-day and without time zone.
We want to compare with current date in UTC. 我们希望与UTC中的当前日期进行比较。
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ; // Specify the offset/zone by which you want to perceive the current date.
Compare. 相比。
if ( ld.isBefore( today ) ) { … }
else if ( ld.isEqual( today ) ) { … }
else if ( ld.isAfter( today ) ) { … }
else { … handle error }
Avoid unnecessarily using custom formats such as "yyyy/MM/dd". 避免不必要地使用自定义格式,例如“yyyy / MM / dd”。 Use standard ISO 8601 formats whenever possible.
尽可能使用标准ISO 8601格式。
For a date-only value, that would be YYYY-MM-DD. 对于仅限日期的值,即YYYY-MM-DD。
String output = LocalDate.now().toString() ; // Ex: 2018-01-23
Here is a full example of writing, querying, and reading LocalDate
objects from a database column of SQL-standard DATE
type. 以下是从SQL标准
DATE
类型的数据库列中编写,查询和读取LocalDate
对象的完整示例。
Using the H2 Database Engine , as I am not a MySQL user. 使用H2数据库引擎 ,因为我不是MySQL用户。 Creating an in-memory database rather than writing to storage.
创建内存数据库而不是写入存储。 I assume the code would be nearly the same for MySQL.
我假设MySQL的代码几乎相同。
try (
Connection conn = DriverManager.getConnection( "jdbc:h2:mem:trashme" )
) {
String sql = "CREATE TABLE " + "tbl_" + " (\n" +
" uuid_ UUID DEFAULT random_uuid() , \n" + // Every table should have a primary key.
" when_ DATE \n" + // Three columns per the Question.
" );";
try (
Statement stmt = conn.createStatement() ;
) {
stmt.execute( sql );
}
sql = "INSERT INTO tbl_ ( when_ ) VALUES ( ? ) ;";
LocalDate start = LocalDate.of( 2018 , Month.JANUARY , 23 );
LocalDate ld = start; // Keep the `start` object for use later.
try (
PreparedStatement ps = conn.prepareStatement( sql )
) {
for ( int i = 1 ; i <= 10 ; i++ ) {
ps.setObject( 1 , ld );
ps.executeUpdate();
// Prepare for next loop.
int randomNumber = ThreadLocalRandom.current().nextInt( 1 , 5 + 1 ); // Pass minimum & ( maximum + 1 ).
ld = ld.plusDays( randomNumber ); // Add a few days, an arbitrary number.
}
}
// Dump all rows, to verify our populating of table.
System.out.println( "Dumping all rows: uuid_ & when_ columns." );
sql = "SELECT uuid_ , when_ FROM tbl_ ; ";
int rowCount = 0;
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
) {
while ( rs.next() ) {
rowCount++;
UUID uuid = rs.getObject( 1 , UUID.class );
LocalDate localDate = rs.getObject( 2 , LocalDate.class );
System.out.println( uuid + " " + localDate );
}
}
System.out.println( "Done dumping " + rowCount + " rows." );
// Dump all rows, to verify our populating of table.
System.out.println( "Dumping rows where `when_` is after " + start + ": uuid_ & when_ columns." );
sql = "SELECT uuid_ , when_ FROM tbl_ WHERE when_ > ? ; ";
rowCount = 0; // Reset count.
final PreparedStatement ps = conn.prepareStatement( sql );
ps.setObject( 1 , start );
try (
ps ;
ResultSet rs = ps.executeQuery() ;
) {
while ( rs.next() ) {
rowCount++;
UUID uuid = rs.getObject( 1 , UUID.class );
LocalDate localDate = rs.getObject( 2 , LocalDate.class );
System.out.println( uuid + " " + localDate );
}
}
System.out.println( "Done dumping " + rowCount + " rows." );
} catch ( SQLException eArg ) {
eArg.printStackTrace();
}
When run. 跑步时
Dumping all rows: uuid_ & when_ columns.
e9c75998-cd67-4ef9-9dce-6c1eed170387 2018-01-23
741c1452-e224-4e5e-95bc-904d8db58b39 2018-01-27
413de43c-a1be-40b6-9ccf-a9b7d9ba873c 2018-01-31
e2aa148f-48b6-4be6-a0fe-f2881b6b5a63 2018-02-03
f498003c-2d8b-446e-ac55-6d7568ce61c3 2018-02-06
c41606d7-8c05-4bba-9f8e-2a0d1f1bb31a 2018-02-09
3df3abe3-1865-4632-99c4-6cd74883c1ee 2018-02-10
914153fe-34f2-4e4f-a91b-944314994839 2018-02-13
96436bdf-80ee-4afe-b55d-f240140ace6a 2018-02-16
82b43f7b-077d-45c1-8c4f-f5b30dfdd44a 2018-02-19
Done dumping 10 rows.
Dumping rows where `when_` is after 2018-01-23: uuid_ & when_ columns.
741c1452-e224-4e5e-95bc-904d8db58b39 2018-01-27
413de43c-a1be-40b6-9ccf-a9b7d9ba873c 2018-01-31
e2aa148f-48b6-4be6-a0fe-f2881b6b5a63 2018-02-03
f498003c-2d8b-446e-ac55-6d7568ce61c3 2018-02-06
c41606d7-8c05-4bba-9f8e-2a0d1f1bb31a 2018-02-09
3df3abe3-1865-4632-99c4-6cd74883c1ee 2018-02-10
914153fe-34f2-4e4f-a91b-944314994839 2018-02-13
96436bdf-80ee-4afe-b55d-f240140ace6a 2018-02-16
82b43f7b-077d-45c1-8c4f-f5b30dfdd44a 2018-02-19
Done dumping 9 rows.
The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
, Calendar
, & SimpleDateFormat
. 这些类取代了麻烦的旧遗留日期时间类,如
java.util.Date
, Calendar
和SimpleDateFormat
。
The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial . 要了解更多信息,请参阅Oracle教程 。 And search Stack Overflow for many examples and explanations.
并搜索Stack Overflow以获取许多示例和解释。 Specification is JSR 310 .
规范是JSR 310 。
You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later.
使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 No need for strings, no need for
java.sql.*
classes. 不需要字符串,不需要
java.sql.*
类。
Where to obtain the java.time classes? 从哪里获取java.time类?
The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time.
该项目是未来可能添加到java.time的试验场。 You may find some useful classes here such as
Interval
, YearWeek
, YearQuarter
, and more . 您可以在这里找到一些有用的类,比如
Interval
, YearWeek
, YearQuarter
,和更多 。
It all depends on the Java version that you are using. 这一切都取决于您使用的Java版本。 If you are using Java 6 or Java 7 then this approach will be the easiest:
如果您使用的是Java 6或Java 7,那么这种方法将是最简单的方法:
As you are dealing with java.sql.Date anyways, you can use this quick approach to get Date without time part and compare java.sql.Date to java.sql.Date: 无论如何,当你正在处理java.sql.Date时,你可以使用这种快速方法来获取没有时间部分的Date,并将java.sql.Date与java.sql.Date进行比较:
Date currentDate = new java.sql.Date(System.currentTimeMillis());
You can also use java.util.Date#before
and java.util.Date#after
methods for the better code readability: 您还可以
java.util.Date#after
方法java.util.Date#before
使用java.util.Date#before
和java.util.Date#after
以获得更好的代码可读性:
while(rs.next()){
System.out.println(dateFormat.format(currentDate));
if (rs.getDate(5).after(currentDate)) {
// System.out.println("Database-date is after currentDate");
} else if (rs.getDate(5).before(currentDate)) {
// System.out.println("Database-date is before currentDate");
PreparedStatement updatexdd = con.prepareStatement(queryy);
updatexdd.setInt(1, rs.getInt(1));
int updatexdd_done = updatexdd.executeUpdate();
} else {
// System.out.println("Database-date is equal to currentDate");
}
}
If you are using Java 8 then you can use new Java time API. 如果您使用的是Java 8,则可以使用新的Java时间API。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.