我正在尝试比较2个日期,第一个日期来自MySQL数据库,第二个日期来自当前日期。
如下所示,数据库中有不同的日期
但问题是我得到3个if语句,它应该告诉我的程序数据库日期是在当前日期之前,之后还是等于当前日期。 Before和After语句应该有效,但是它可以看到2018-06-12的日期应该等于当前日期,所以它在" before语句中结束"。
希望你能看到我做错了什么。
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");
}
}
}
答案 0 :(得分:4)
ResultSet#getDate
返回删除时间部分的日期。实例化新的Date
对象确实包含时间,因此您必须自行删除它。 E.g:
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();
答案 1 :(得分:3)
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 }
你正在使用和滥用麻烦的旧日期时间课程。
正如其他人所指出的那样:
DATE
类型仅包含没有时间且没有时区的日期java.util.Date
类名称错误,日期和的日期为UTC。java.sql.Date
类假装只持有一个日期,但实际上有一个时间,因为这个类继承了上面的那个,而文档告诉我们在我们的用法中忽略这个事实。 (是的,这很令人困惑,而且是一个糟糕的设计,一个笨拙的黑客。)切勿使用java.util.Date
,java.util.Calendar
,java.sql.Timestamp
,java.sql.Date
及相关课程。相反,只使用理智的 java.time 类。他们从其前身Joda-Time项目的经验中获得了清洁设计和对日期时间处理的深入理解,引领行业发展。
对于仅限日期的值,存储在SQL标准数据库类型DATE
中,请使用java.time.LocalDate
。
LocalDate ld = myResultSet.get( … , LocalDate.class ) ; // Retrieving from database.
myPreparedStatement.setObject( … , ld ) ; // Storing in database.
对于以UTC值表示时间的日期,存储在SQL标准数据库类型TIMESTAMP WITH TIME ZONE
中,请使用java.time.Instant
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant instant = myResultSet.get( … , Instant.class ) ; // Retrieving from database.
myPreparedStatement.setObject( … , instant ) ; // Storing in database.
要在Java中进行比较,请使用isEqual
,isBefore
,isAfter
,equals
或compare
方法。
Boolean overdue = someLocalDate.isAfter( otherLocalDate ) ;
时区对于确定某个时刻(Instant
/ TIMESTAMP WITH TIME ZONE
)的日期和时间至关重要。
从TIMESTAMP WITH TIME ZONE
中检索数据库中的Instant
值后,请调整time zone或offset-from-UTC,以便在感知日期时使用其挂钟时间&安培;时间的天。对于时区,请应用ZoneId
以获取ZonedDateTime
对象。对于来自UTC的偏移量,请应用ZoneOffset
来获取OffsetDateTime
对象。在任何一种情况下,都可以通过调用toLocalDate
来获取LocalDate
对象来提取仅限日期的值。
在您的情况下,您显然希望将日期视为UTC。因此,应用常量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.
我们希望与UTC中的当前日期进行比较。
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ; // Specify the offset/zone by which you want to perceive the current date.
比较
if ( ld.isBefore( today ) ) { … }
else if ( ld.isEqual( today ) ) { … }
else if ( ld.isAfter( today ) ) { … }
else { … handle error }
避免不必要地使用自定义格式,例如“yyyy / MM / dd”。尽可能使用标准ISO 8601格式。
对于仅限日期的值,即YYYY-MM-DD。
String output = LocalDate.now().toString() ; // Ex: 2018-01-23
以下是从SQL标准LocalDate
类型的数据库列中编写,查询和读取DATE
对象的完整示例。
使用H2 Database Engine,因为我不是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();
}
跑步时。
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.
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:2)
这完全取决于您使用的Java版本。如果您使用的是Java 6或Java 7,那么这种方法将是最简单的方法:
当你正在处理java.sql.Date时,你可以使用这种快速方法来获取没有时间部分的Date并将java.sql.Date与java.sql.Date进行比较:
Date currentDate = new java.sql.Date(System.currentTimeMillis());
您还可以使用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");
}
}
如果您使用的是Java 8,则可以使用新的Java时间API。