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