Compare Date object with a TimeStamp in Java

后端 未结 10 866
悲&欢浪女
悲&欢浪女 2020-12-09 02:32

When I test this code:

java.util.Date date = new java.util.Date();
java.util.Date stamp = new java.sql.Timestamp(date.getTime());

assertTrue(date.equals(sta         


        
相关标签:
10条回答
  • 2020-12-09 03:19

    tl;dr

    Use the modern java.time classes instead of those troublesome legacy date-time classes.

    myPreparedStatement.setObject(
        … , 
        Instant.now()                // Capture the current moment in UTC.
    )
    

    Old Date-Time Classes Poorly Designed

    Put more bluntly, the java.sql.Timestamp/.Date/.Time classes are a hack, a bad hack. Like java.util.Date/.Calendar, they are the result of poor design choices.

    The java.sql types should be used as briefly as possible, used only for transfer of data in/out of the database. Do not use for business logic and further work.

    java.time

    The old date-time classes have been replaced by the java.time framework built into Java 8 and later. These new classes are defined by JSR 310, inspired by the highly successful Joda-Time library, and extended by the ThreeTen-Extra project.

    Eventually we should see JDBC drivers updated to work directly with these java.time types. But until that day we need to convert to/from java.sql types. For such conversions, call new methods added to the old classes.

    An Instant is a moment on the timeline in UTC to a resolution of nanoseconds.

    Instant instant = myJavaSqlTimestamp.toInstant();
    

    To go the other direction:

    java.sql.Timestamp ts = java.sql.Timestamp.valueOf( instant );
    

    Apply a time zone to get wall-clock time.

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
    

    The java.time classes have a clean wisely-chosen class design. So you can use the equals and compareTo as expected. Note that the classes with an offset-from-UTC or time zone also offer isEqual, isBefore, and isAfter methods. These methods compare by considering moments on the timeline, their chronological order. The equals and compareTo methods also consider the offset or time zone.

    Minimizing the use of java.sql while maximizing the use of java.time renders the Question’s issues moot.

    In Hibernate, use converters for java.time.

    JDBC 4.2

    As of JDBC 4.2 and later, you need not use the legacy classes at all. You can directly exchange java.time objects with your database via the getObject & setObject methods.

    myPreparedStatement.setObject( … , instant ) ;
    

    And retrieval.

    Instant instant = myResultSet.getObject( … , Instant.class ) ;
    

    Note that many databases cannot store a moment with a resolution as fine as the nanoseconds used in java.time. You may want to truncate explicitly rather than letting your JDBC driver do so implicitly.

    Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Lop off any nanoseconds & microseconds, keeping only the milliseconds, to match limitations of database. 
    

    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

    Where to obtain the java.time classes?

    • Java SE 8, Java SE 9, Java SE 10, and later
      • Built-in.
      • Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.
    • Java SE 6 and Java SE 7
      • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • Android
      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

    The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

    0 讨论(0)
  • 2020-12-09 03:20

    Sadly, the Timestamp class do overloads the equals(Object) method with equals(Timestamp) so comparisons on Timestamps are hard to do.

    In the equals(Object) javadocs says:

    Tests to see if this Timestamp object is equal to the given object. This version of the method equals has been added to fix the incorrect signature of Timestamp.equals(Timestamp) and to preserve backward compatibility with existing class files. Note: This method is not symmetric with respect to the equals(Object) method in the base class.

    My rule of thumb is never to compare timestamps for equality (which is pretty much useless anyway), but if you do have to check for equality, compare them using the result of getTime() (the number of milliseconds from january 1st 1970, 00:00).

    0 讨论(0)
  • 2020-12-09 03:27

    Try recreate the object date using "Strings" like this

    Date date = new Date();
    Date stamp = Timestamp(date.getTime());
    
    SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    String date1String = ft.format(date);
    String date2String = ft.format(stamp);
    
    Date date1 = ft.parse(date1String);
    Date date2 = ft.parse(date2String);
    
    
    assertTrue(date1.equals(date2)); // true
    assertTrue(date1.compareTo(date2) == 0); //true
    assertTrue(date2.compareTo(date1) == 0); //true
    assertTrue(date2.equals(date1)); // true
    
    0 讨论(0)
  • 2020-12-09 03:30

    I had the same problem in a test where I wanted to compare java.util.Date and java.sql.Timestamp objects.

    I converted them to LocalDate and that worked:

    import org.apache.commons.lang.ObjectUtils;
    
    // date1 and date2 can be java.util.Date or java.sql.Timestamp
    boolean datesAreEqual = ObjectUtils.equals(toLocalDate(date1), toLocalDate(date2));
    

    where toLocalDate is:

    import org.joda.time.LocalDate;
    import java.util.Date;
    
    public static void LocalDate toLocalDate(Date date)
    {
        return date != null ? LocalDate.fromDateFields(date) : null;
    }
    
    0 讨论(0)
提交回复
热议问题