Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

en utilisant le type de données datetimeoffset avec jTDS

Comme mentionné dans la section "Compatibilité descendante pour les clients de niveau inférieur" de datetimeoffset documents , nous pouvons travailler avec des représentations sous forme de chaîne de datetimeoffset valeurs. En fait, si on récupère un datetimeoffset valeur avec jTDS 1.3.1 nous obtenons un java.lang.String valeur du formulaire

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

Une telle valeur peut être analysée comme suit :

// 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);

Comme pour écrire un datetimeoffset valeur à SQL Server, jTDS est incapable de gérer correctement une mise à jour à l'aide de .setTimestamp , par exemple, sur ma machine ...

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

... produit ...

         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

... qui non seulement définit incorrectement le décalage du fuseau horaire sur +00:00 (sans changer la valeur date/heure elle-même), mais ajoute également quelques millisecondes juste pour le plaisir.

Cependant, si nous convertissons la valeur d'horodatage en une chaîne correctement formatée, par exemple, ...

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

... et utilisez .setString au lieu de .setTimestamp , puis le datetimeoffset la valeur est correctement enregistrée :

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