JDBC Timestamp & Date GMT issues

前端 未结 5 1081
夕颜
夕颜 2021-02-06 05:20

I have a JDBC Date column, which if a i use getDate is get the \'date\' part only 02 Oct 2009 but if i use getTimestamp i get the full \'date\

相关标签:
5条回答
  • 2021-02-06 05:32

    That's the difference between Timestamp and other temporal types in MySQL. Timestamp is saved as Unix time_t in UTC but other types store date/time literally without zone information.

    When you call getTimestamp(), MySQL JDBC driver converts the time from GMT into default timezone if the type is timestamp. It performs no such conversion for other types.

    You can either change the column type or do the conversion yourself. I recommend former approach.

    0 讨论(0)
  • 2021-02-06 05:40

    You should be aware that java.util.Date (and also java.sql.Date and java.sql.Timestamp, which are subclasses of java.util.Date) don't know anything about timezones, or rather, they are always in UTC.

    java.util.Date and its subclasses are nothing more than a container for a "number of milliseconds since 01-01-1970, 12:00 AM UTC" value.

    To display a date in a specific timezone, convert it to a string by using a java.text.DateFormat object. Set the timezone on that object by calling the setTimeZone() method. For example:

    Date date = ...;  // wherever you get this from
    
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    // Make the date format show the date in CET (central European time)
    df.setTimeZone(TimeZone.getTimeZone("CET"));
    
    String text = df.format(date);
    
    0 讨论(0)
  • 2021-02-06 05:42

    I ran into a similar problem the other day where the time component was being truncated from some dates.

    We narrowed it down to a difference in Oracle Driver versions.

    On Oracle's FAQ there is a section about this:


    select sysdate from dual; ...while(rs.next())
    

    Prior to 9201, this will return: getObject for sysdate : java.sql.Timestamp <<<< getDate for sysdate : java.sql.Date getTimetamp for sysdate : java.sql.Timestamp

    As of 9201 onward the following will be returned

    getObject for sysdate : java.sql.Date <<<<< getDate for sysdate :java.sql.Date >> no change getTimetamp for sysdate :java.sql.Timestamp >> no change

    Note: java.sql.Date has no time portion whereas java.sql.Timestamp does.

    With this change in Datatype mapping, some application will fail and/or generate incorrect results when JDBC driver is upgraded from 8i/ 9iR1 to 920x JBDC driver. To maintain compatibility and keep applications working after upgrade, a compatibility flag was Provided. Developers now have some options:

    1. Use oracle.jdbc.V8Compatible flag.

    JDBC Driver does not detect database version by default. To change the compatibility flag for handling TIMESTAMP datatypes, connection property

    'oracle.jdbc.V8Compatible'

    can be set to 'true' and the driver behaves as it behaved in 8i, 901x, 9 200 (with respect to TIMESTAMPs).

    By default the flag is set to 'false'. In OracleConnection constructor the driver obtains the server version and set the compatibility flag appropriately.

    java.util.Properties prop=newjava.util.Properties(); 
    prop.put("oracle.jdbc.V8Compatible","true"); 
    prop.put("user","scott"); 
    prop.put("password","tiger");
    String url="jdbc:oracle:thin:@host:port:sid"; 
    Connection conn = DriverManager.getConnection(url,prop);
    

    With JDBC 10.1.0.x, instead of the connection property, the following system property can be used: java -Doracle.jdbc.V8Compatible=true.....Note: This flag is a client only flag that governs the Timestamp and Date mapping. It does not affect any Database feature.

    '2. Use set/getDate and set/getTimestamp when dealing with Date and TimeStamp column data type accordingly.

    9i server supports both Date and Timestamp column types DATE is mapped to java.sql.Date and TIMESTAMP is mapped to java.sql.Timestamp.


    So for my situation, I had code like this:

    import java.util.Date; 
    Date d = rs.getDate(1);
    

    With 9i I was getting a java.sql.Timestamp (which is a subclass of java.util.Date) so everything was groovy and I had my hours and minutes.

    But with 10g, the same code now gets a java.sql.Date (also a subclass of java.util.Date so it still compiles) but the HH:MM is TRUNCATED!!.

    The 2nd solution was pretty easy for me - just replace the getDate with getTimestamp and you should be OK. I guess that was a bad habit.

    0 讨论(0)
  • 2021-02-06 05:51

    From this post i have come to the conclusion that JDBC does retrieve the timezone for the Timestamp (I don't think MS SQL support this as well, most Google results point to Oracle)

    When the JDBC getTimeStamp method is called it only gets the 'milliseconds' portion and create a Date object with the server TimeZone, which is GMT.

    When this Date object is presented to my client which is +2 GMT, it adds 2 hours which is the standard offset which leads to the extra hours.

    I have corrected this by removing the time offset from the date i retrieve i.e. convert to the true GMT Date.

    0 讨论(0)
  • 2021-02-06 05:52
    private Date convertDate(Date date1) throws ParseException {
            SimpleDateFormat sdfFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateStr = sdfFormatter.format(date1);
            SimpleDateFormat sdfParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdfParser.setTimeZone(TimeZone.getTimeZone("GMT"));
            return sdfParser.parse(dateStr);
        }
    
    0 讨论(0)
提交回复
热议问题