Java CompareTo Даты не могут быть равны - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь сравнить 2 даты, первая дата из базы данных MySQL, а вторая из текущей даты.

Как вы можете видеть ниже, в базе данных есть разные даты

Dates records in database Но проблема в том, что я получил 3 оператора if, которые должны сообщать моей программеесли дата базы данных раньше, позже или равна текущей дате.Операторы «До» и «После» должны работать, но он может видеть, что дата 2018-06-12 должна совпадать с текущей датой, поэтому он заканчивается в «операторе до».

Надеюсь, вы увидите, что я сделалнеправильно.

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");
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Все зависит от используемой вами версии Java.Если вы используете Java 6 или Java 7, тогда этот подход будет самым простым:

Поскольку вы имеете дело с java.sql.Date в любом случае, вы можете использовать этот быстрый подход, чтобы получить Date без временной части и сравнить java.sql.Date to 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, вы можете использовать новый API времени Java.

0 голосов
/ 13 июня 2018

tl; dr

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 }

java.time

Вы используете и неправильно используете старые классы даты и времени.

Как отмечали другие:

  • Стандартный DATE тип SQL содержит только дату без времени суток и без часового пояса
  • унаследованный класс 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 с разрешением наносекунд (до девяти (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, настройте в часовой пояс или смещение-от-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 }

ISO 8601

Избегайте ненужного использования пользовательских форматов, таких как "гггг / мм / дд".По возможности используйте стандартные форматы ISO 8601 .

Для значения только для даты это будет ГГГГ-ММ-ДД.

String output = LocalDate.now().toString() ;  // Ex: 2018-01-23

Пример с H2

Вот полный пример написания, запроса и чтения LocalDate объектов из столбца базы данных стандарта SQL 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.time Framework встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 и позже
    • Встроенный.
    • Часть стандартного Java API с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализации комплекта Android-классов java.time.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

0 голосов
/ 12 июня 2018

ResultSet#getDate возвращает дату с удаленной частью времени.Создание нового Date объекта содержит время, поэтому вам придется удалить его самостоятельно.Например:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...