Search code examples
javadatecommonjsdo

Get Date from a DataObject (SDO) without losing the hour (JAVA)


I'm trying to get a date from a DataObject (Service Date Object (SDO)) that comes to me as an input and insert it into an Oracle database. The problem has been that the Date I get does not seem to have the introduced hour.

I am using the setDate() method from DataObject with the following value: 2019-05-22T13:30:00Z.

For some reason, when using getDate() what is returning is the day entered with the hour set at 0 (2019-05-22 00:00:00).

I'm not sure if it's due to the input format or something related to the Date class from java.utils.

An easy solution would be to pass it as String and convert it into Date using a format but I would like to save this intermediate step.


Solution

  • java.util.Date versus java.sql.Date

    Your Question does not provide enough detail to know for sure, but I can take an educated guess.

    returning is the day entered with the hour set at 0 (2019-05-22 00:00:00).

    I suspect your code calling setDate and/or getDate is using a java.sql.Date object rather than a java.util.Date object.

    Check your import statements. If you used the wrong class by accident, that would explain the time-of-day getting set to 00:00.

    • java.util.Date represents a moment in UTC (a date, a time-of-day, and an offset-from-UTC of zero hours-minutes-seconds).
    • java.sql.Date pretends to represent a date-only, without a time-of-day and without a time zone or offset-from-UTC. Actually does contain a time-of-day and offset, but tries to adjust the time to 00:00:00.0 as part of the pretense.

    Confusing? Yes. These old date-time classes from the earliest days of Java are a bloody awful mess, built by people who did not understand the complexities of date-time handling. Avoid these legacy date-time classes!

    These legacy classes were supplanted years ago by the modern java.time classes defined in JSR 310. Try to do all your work in java.time. When interoperating with old code such as SDO that is not yet updated for java.time, call on new conversion methods added to the old classes.

    The modern replacement of a java.util.Date is java.time.Instant. Both represents a moment in UTC, though Instant has a finer resolution of nanoseconds versus milliseconds.

    Instant instant = Instant.now() ;  // Capture the current moment in UTC.
    

    Convert from modern class to legacy class. Beware of data-loss: Any microseconds or nanoseconds in the fractional second are truncated to milliseconds (as noted above).

    java.util.Date d = java.util.Date.from( instant ) ;  // Convert from modern to legacy. Truncates any microseconds or nanoseconds.
    

    Pass to your SDO object.

    mySdoDataObject.setDate( d ) ;
    

    Going the other direction, retrieve the legacy java.util.Date object and immediately convert to an Instant.

    Instant instant = mySdoDataObject.getDate().toInstant() ;  
    

    To see that same moment through the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime object.

    ZoneId z = ZoneId.of( "America/Montreal" ) ;
    ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, different wall-clock time.
    

    An easy solution would be to pass it as String

    No! Use smart objects, not dumb strings. We have the industry-leading date-time library built into Java, so use it.

    Database

    As of JDBC 4.2, we can directly exchange java.time objects with the database.

    Table of date-time types for Java (both legacy & modern) and for standard SQL.

    Your JDBC driver may optionally handle Instant. If not, convert to OffsetDateTime.

    OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
    myPreparedStatement.setObject( … , odt ) ;
    

    Retrieval.

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

    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.

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

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

    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?

    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.