Je dois stocker UTC dateTime dans DB.
J'ai converti l'heure UTC indiquée dans un fuseau horaire spécifique. pour cela j'ai suivi le code ci-dessous.
La date et l'heure de mon entrée est "20121225 10:00:00 Z" le fuseau horaire est "Asie/Calcutta".
Mon serveur/ma base de données (Oracle) s'exécute dans le même fuseau horaire (IST) "Asie/Calcutta"
récupère l'objet Date dans ce fuseau horaire spécifique
String date = "20121225 10:00:00 Z";
String timeZoneId = "Asia/Calcutta";
TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
DateFormat dateFormatLocal = new SimpleDateFormat("yyyyMMdd HH:mm:ss z");
//This date object is given time and given timezone
Java.util.Date parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(false, TimeZone.SHORT));
if (timeZone.inDaylightTime(parsedDate)) {
// We need to re-parse because we don't know if the date
// is DST until it is parsed...
parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(true, TimeZone.SHORT));
}
//assigning to the Java.sql.TimeStamp instace variable
obj.setTsSchedStartTime(new Java.sql.Timestamp(parsedDate.getTime()));
stocker dans la base de données
if (tsSchedStartTime != null) {
stmt.setTimestamp(11, tsSchedStartTime);
} else {
stmt.setNull(11, Java.sql.Types.DATE);
}
SORTIE
La base de données (Oracle) a stocké la même donnée dateTime: "20121225 10:00:00
Pas en UTC.
J'ai confirmé de ci-dessous sql.
select to_char(sched_start_time, 'yyyy/mm/dd hh24:mi:ss') from myTable
Mon serveur de base de données fonctionne également sur le même fuseau horaire "Asie/Calcutta"
Il me donne les apparences ci-dessous
Date.getTime()
n'est pas en UTCne autre question:
Est-ce que timeStamp.toString()
imprimera dans le fuseau horaire local comme le fait Java.util.date
? Pas UTC?
Bien que cela ne soit pas explicitement spécifié pour setTimestamp(int parameterIndex, Timestamp x)
, les pilotes doivent suivre les règles établies par le setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
javadoc :
Définit le paramètre désigné sur la valeur
Java.sql.Timestamp
Donnée, à l'aide de l'objetCalendar
donné. Le pilote utilise l'objetCalendar
pour construire une valeur SQLTIMESTAMP
qu'il envoie ensuite à la base de données. Avec un objetCalendar
, le pilote peut calculer l’horodatage en tenant compte d’un fuseau horaire personnalisé. Si aucun objetCalendar
n'est spécifié, le pilote utilise le fuseau horaire par défaut, qui est celui de la machine virtuelle exécutant l'application.
Lorsque vous appelez avec setTimestamp(int parameterIndex, Timestamp x)
, le pilote JDBC utilise le fuseau horaire de la machine virtuelle pour calculer la date et l'heure de l'horodatage dans ce fuseau horaire. Cette date et cette heure correspondent à ce qui est stocké dans la base de données. Si la colonne de la base de données ne stocke pas les informations de fuseau horaire, toutes les informations relatives à la zone sont perdues (c’est-à-dire que les applications utilisant la base de données utilisent le toujours le même fuseau horaire ou avec un autre schéma pour distinguer le fuseau horaire (c.-à-d. le stocker dans une colonne séparée).
Par exemple: Votre fuseau horaire local est GMT + 2. Vous stockez "2012-12-25 10:00:00 UTC". La valeur réelle stockée dans la base de données est "2012-12-25 12:00:00". Vous le récupérez à nouveau: vous le récupérez sous le nom "2012-12-25 10:00:00 UTC" (uniquement si vous le récupérez à l'aide de getTimestamp(..)
), mais lorsqu'une autre application accède à la base de données dans le fuseau horaire. GMT + 0, l’horodatage sera "2012-12-25 12:00:00 UTC".
Si vous souhaitez le stocker dans un fuseau horaire différent, vous devez utiliser setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
avec une instance de calendrier dans le fuseau horaire requis. Assurez-vous simplement que vous utilisez également le getter équivalent avec le même fuseau horaire lors de la récupération de valeurs (si vous utilisez un TIMESTAMP
sans information de fuseau horaire dans votre base de données).
Donc, en supposant que vous souhaitiez stocker le fuseau horaire GMT réel, vous devez utiliser:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
stmt.setTimestamp(11, tsSchedStartTime, cal);
Avec JDBC 4.2, un pilote conforme devrait prendre en charge Java.time.LocalDateTime
(Et Java.time.LocalTime
) Pour TIMESTAMP
(et TIME
) à get/set/updateObject
. Les classes Java.time.Local*
Étant dépourvues de fuseau horaire, aucune conversion ne doit être appliquée (bien que cela puisse poser de nouveaux problèmes si votre code supposait un fuseau horaire spécifique).
Je pense que la réponse correcte devrait être Java.sql.Timestamp N'EST PAS spécifique au fuseau horaire. L'horodatage est un composite de Java.util.Date et d'une valeur séparée en nanosecondes. Il n'y a pas d'informations de fuseau horaire dans cette classe. Ainsi, tout comme Date, cette classe contient simplement le nombre de millisecondes écoulées depuis le 1er janvier 1970, 00:00:00 GMT + nanos.
Dans PreparedStatement.setTimestamp (int parametreIndex, Horodatage x, calage du calendrier), le pilote utilise le calendrier pour modifier le fuseau horaire par défaut. Mais l'horodatage a toujours une durée millisecondes en GMT.
L'API ne sait pas exactement comment le pilote JDBC est censé utiliser Calendar. Les fournisseurs semblent être libres de l’interpréter, par exemple. la dernière fois que j'ai travaillé avec MySQL 5.5 Calendar, le pilote n'a tout simplement pas tenu compte de Calendar, tant dans PreparedStatement.setTimestamp que dans ResultSet.getTimestamp.
C'est spécifique de votre pilote. Vous devez fournir un paramètre dans votre programme Java pour lui indiquer le fuseau horaire que vous souhaitez utiliser.
Java -Duser.timezone="America/New_York" GetCurrentDateTimeZone
De plus ceci:
to_char(new_time(sched_start_time, 'CURRENT_TIMEZONE', 'NEW_TIMEZONE'), 'MM/DD/YY HH:MI AM')
Peut également être utile pour gérer correctement la conversion. Tiré de ici
Pour Mysql, nous avons une limitation. Dans le pilote Mysql doc , nous avons:
Voici quelques problèmes et limitations connus de MySQL Connector/J: Lorsque Connector/J récupère les horodatages d'un jour de commutation d'heure d'été à l'aide de la méthode getTimeStamp () sur le jeu de résultats, certaines des valeurs renvoyées peuvent être erronées. Les erreurs peuvent être évitées en utilisant les options de connexion suivantes lors de la connexion à une base de données:
useTimezone=true
useLegacyDatetimeCode=false
serverTimezone=UTC
Ainsi, lorsque nous n'utilisons pas ces paramètres et que nous appelons setTimestamp or getTimestamp
avec calendrier ou sans calendrier, nous avons l’horodatage dans le fuseau horaire jvm.
Exemple :
Le fuseau horaire jvm est GMT + 2. Dans la base de données, nous avons un horodatage: 1461100256 = 19/04/16 21: 10: 56,000000000 GMT
Properties props = new Properties();
props.setProperty("user", "root");
props.setProperty("password", "");
props.setProperty("useTimezone", "true");
props.setProperty("useLegacyDatetimeCode", "false");
props.setProperty("serverTimezone", "UTC");
Connection con = DriverManager.getConnection(conString, props);
......
Calendar nowGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Calendar nowGMTPlus4 = Calendar.getInstance(TimeZone.getTimeZone("GMT+4"));
......
rs.getTimestamp("timestampColumn");//Oracle driver convert date to jvm timezone and Mysql convert date to GMT (specified in the parameter)
rs.getTimestamp("timestampColumn", nowGMT);//convert date to GMT
rs.getTimestamp("timestampColumn", nowGMTPlus4);//convert date to GMT+4 timezone
La première méthode renvoie: 1461100256000 = 19/04/2016 - 21:10:56 GMT
La seconde méthode renvoie: 1461100256000 = 19/04/2016 - 21:10:56 GMT
La troisième méthode renvoie: 1461085856000 = 19/04/2016 - 17:10:56 GMT
Au lieu d'Oracle, lorsque nous utilisons les mêmes appels, nous avons:
La première méthode retourne: 1461093056000 = 19/04/2016 - 19:10:56 GMT
La seconde méthode renvoie: 1461100256000 = 19/04/2016 - 21:10:56 GMT
La troisième méthode renvoie: 1461085856000 = 19/04/2016 - 17:10:56 GMT
NB: Il n'est pas nécessaire de spécifier les paramètres pour Oracle.