2016-04-04 24 views
4

jTDS derzeit nicht unterstützt datetimeoffset Datentyp in SQL Server eingeführt 2008.den Datetimedatentyp mit jTDS mit

Kann jemand vorschlagen, wenn es eine Möglichkeit, den datetimeoffset Typen mit jTDS zu verwenden ist?

+0

Sie können den Fehlerbericht hier verfolgen https://sourceforge.net/p/jtds/bugs/681/ –

Antwort

1

Wie im Abschnitt "Abwärtskompatibilität für Down-Level-Clients" der datetimeoffset documentation erwähnt, können wir mit String-Darstellungen von datetimeoffset Werten arbeiten. In der Tat erhalten wir einen java.lang.String Wert der Form, wenn wir einen datetimeoffset Wert mit jTDS 1.3.1 abrufen

YYYY-MM-DD hh:mm:ss[.nnnnnnn] {+|-}hh:mm 

Ein solcher Wert kann wie so analysiert werden:

// rs is our ResultSet object 
String valueRetrieved = rs.getString(1); // e.g., "2016-12-08 12:34:56.7850000 -07:00" 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS ZZZZZ"); 
ZonedDateTime zdt = ZonedDateTime.parse(valueRetrieved, dtf); 

Wie für einen datetimeoffset Schreiben Wert auf SQL Server, ist jTDS nicht in der Lage ein Update mit .setTimestamp, zB richtig zu handhaben, auf meinem Rechner ...

java.sql.Timestamp ts = java.sql.Timestamp.valueOf("2016-12-08 12:34:56.785"); // local 
String tsString = formatTimestampForDateTimeOffset(ts); // (see below) 
System.out.printf("    java.sql.TimeStamp value: %s (%d ms since epoch)%n", tsString, ts.getTime()); 

System.out.println(); 
System.out.println("Saving via setTimestamp ..."); 
String sqlUpdate = "UPDATE dtoTable SET dtoCol = ? WHERE id=1"; 
try (PreparedStatement s = conn.prepareStatement(sqlUpdate)) { 
    s.setTimestamp(1, ts); // pass the Timestamp itself 
    s.executeUpdate(); 
} 
String valueRetrieved; 
try (
     Statement s = conn.createStatement(); 
     ResultSet rs = s.executeQuery("SELECT dtoCol FROM dtoTable WHERE id=1")) { 
    rs.next(); 
    valueRetrieved = rs.getString(1); 
    System.out.printf(" jTDS saved the TimeStamp value as: %s%n", valueRetrieved); 
} 

... produziert ...

  java.sql.TimeStamp value: 2016-12-08 12:34:56.785 -07:00 (1481225696785 ms since epoch) 

Saving via setTimestamp ... 
jTDS saved the TimeStamp value as: 2016-12-08 12:34:56.7870000 +00:00 

..., das nicht nur falsch, die Zeitzone +00 Offset setzt: 00 (ohne Änderung des Datums-/Uhrzeitwert selbst), es fügt auch ein paar Millisekunden nur zum Spaß.

Wenn wir jedoch den Zeitstempelwert auf eine korrekt formatierte String konvertieren, zB ...

public static String formatTimestampForDateTimeOffset(java.sql.Timestamp ts) { 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ZZZZZ"); 
    String s = sdf.format(new Date(ts.getTime())); 
    // T-SQL *requires* the colon in the timezone offset: -07:00, not -0700 
    int colonPosition = s.length() - 2; 
    return s.substring(0, colonPosition) + ":" + s.substring(colonPosition); 
} 

... und verwenden .setString statt .setTimestamp, dann wird der datetimeoffset Wert korrekt gespeichert:

Saving via setString ... 
jTDS saved the formatted String as: 2016-12-08 12:34:56.7850000 -07:00 
      parsed to ZonedDateTime: 2016-12-08T12:34:56.785-07:00 
       converted to Instant: 2016-12-08T19:34:56.785Z 
     converted to java.util.Date: Thu Dec 08 12:34:56 MST 2016