J'ai une valeur d'horodatage qui provient de mon application. L'utilisateur peut se trouver dans n'importe quelle zone horaire locale.
Puisque cette date est utilisée pour un WebService qui suppose que l'heure donnée est toujours en GMT, j'ai besoin de convertir le paramètre de l'utilisateur de disons (EST) à (GMT). Voici le kicker: l'utilisateur est inconscient de son TZ. Il entre la date de création qu'il souhaite envoyer au WS, donc j'ai besoin de:
L'utilisateur entre: 5/1/2008 6:12 PM (EST)
Le paramètre du WS doit être : 5/1/2008 6:12 PM (GMT)
Je sais que les horodatages sont toujours censés être en GMT par défaut, mais lors de l'envoi du paramètre, même si j'ai créé mon calendrier à partir du TS (qui est censé être en GMT), les heures sont toujours éteintes sauf si l'utilisateur est en GMT. Qu'est-ce que je rate?
Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
...
private static java.util.Calendar convertTimestampToJavaCalendar(Timestamp ts_) {
java.util.Calendar cal = java.util.Calendar.getInstance(
GMT_TIMEZONE, EN_US_LOCALE);
cal.setTimeInMillis(ts_.getTime());
return cal;
}
Avec le code précédent, voici ce que j'obtiens en conséquence (format court pour une lecture facile):
[1er mai 2008 23h12]
Réponses:
Voici la sortie si je passe l'heure actuelle ("12:09:05 EDT" de
Calendar.getInstance()
) dans:12:09:05 GMT est 8:09:05 EDT.
La partie déroutante ici est que
Calendar.getTime()
vous renvoie unDate
dans votre fuseau horaire actuel, et aussi qu'il n'y a pas de méthode pour modifier le fuseau horaire d'un calendrier et faire rouler la date sous-jacente également. En fonction du type de paramètre utilisé par votre service Web, vous souhaiterez peut-être simplement avoir l'accord WS en millisecondes à partir de l'époque.la source
offsetFromUTC
au lieu de l'ajouter? En utilisant votre exemple, si 12:09 GMT est 8:09 EDT (ce qui est vrai), et que l'utilisateur entre "12:09 EDT", l'algorithme devrait afficher "16:09 GMT", à mon avis.Merci à tous d'avoir répondu. Après une enquête plus approfondie, j'ai trouvé la bonne réponse. Comme mentionné par Skip Head, l'horodatage que je recevais de mon application était ajusté à la zone horaire de l'utilisateur. Donc, si l'utilisateur entrait 18h12 (EST), j'obtiendrais 14h12 (GMT). Ce dont j'avais besoin était un moyen d'annuler la conversion afin que l'heure saisie par l'utilisateur soit l'heure que j'ai envoyée à la requête du serveur Web. Voici comment j'ai accompli cela:
La sortie du code est: (L'utilisateur a saisi 5/1/2008 6:12 PM (EST)
Fuseau horaire de l' utilisateur actuel: EST Décalage actuel par rapport à GMT (en heures): - 4 (normalement -5, sauf est ajusté à l'heure d'été)
TS de ACP: 2008-05-01 14: 12: 00.0
Date calendaire convertie à partir de TS en utilisant GMT et US_EN Locale : 01/05/08 à 18h12 (GMT)
la source
Vous dites que la date est utilisée en relation avec les services Web, donc je suppose qu'elle est sérialisée dans une chaîne à un moment donné.
Si tel est le cas, vous devriez jeter un œil à la méthode setTimeZone de la classe DateFormat. Cela détermine le fuseau horaire qui sera utilisé lors de l'impression de l'horodatage.
Un exemple simple:
la source
Vous pouvez le résoudre avec Joda Time :
Java 8:
la source
Il semble que votre TimeStamp soit réglé sur le fuseau horaire du système d'origine.
Ceci est obsolète, mais cela devrait fonctionner:
La méthode non obsolète consiste à utiliser
mais cela devrait être fait du côté client, car ce système sait dans quel fuseau horaire il se trouve.
la source
Méthode de conversion d'une timeZone à une autre (cela fonctionne probablement :)).
la source
Les objets Date et Horodatage sont inconscients du fuseau horaire: ils représentent un certain nombre de secondes depuis l'époque, sans s'engager dans une interprétation particulière de cet instant en heures et en jours. Les fuseaux horaires n'entrent dans l'image que dans GregorianCalendar (pas directement nécessaire pour cette tâche) et SimpleDateFormat , qui nécessitent un décalage de fuseau horaire pour convertir entre des champs séparés et des valeurs de date (ou longues ).
Le problème de l'OP est juste au début de son traitement: l'utilisateur saisit les heures, qui sont ambiguës, et elles sont interprétées dans le fuseau horaire local, non GMT; à ce stade, la valeur est "6:12 EST" , qui peut être facilement imprimée comme "11.12 GMT" ou tout autre fuseau horaire mais ne changera jamais en "6.12 GMT" .
Il n'y a aucun moyen de rendre le SimpleDateFormat qui analyse "06:12" comme "HH: MM" (par défaut au fuseau horaire local) par défaut à UTC; SimpleDateFormat est un peu trop intelligent pour son propre bien.
Cependant, vous pouvez convaincre n'importe quelle instance SimpleDateFormat d'utiliser le bon fuseau horaire si vous le mettez explicitement dans l'entrée: ajoutez simplement une chaîne fixe à la réception (et correctement validée) "06:12" pour analyser "06:12 GMT" comme "HH: MM z" .
Il n'est pas nécessaire de définir explicitement les champs GregorianCalendar ou de récupérer et d'utiliser les décalages de fuseau horaire et d'heure d'été.
Le vrai problème est de séparer les entrées par défaut sur le fuseau horaire local, les entrées par défaut sur UTC et les entrées qui nécessitent vraiment une indication de fuseau horaire explicite.
la source
Quelque chose qui a fonctionné pour moi dans le passé était de déterminer le décalage (en millisecondes) entre le fuseau horaire de l'utilisateur et l'heure GMT. Une fois que vous avez le décalage, vous pouvez simplement ajouter / soustraire (en fonction de la façon dont la conversion se déroule) pour obtenir l'heure appropriée dans l'un ou l'autre fuseau horaire. J'accomplirais généralement cela en définissant le champ millisecondes d'un objet Calendar, mais je suis sûr que vous pouvez facilement l'appliquer à un objet d'horodatage. Voici le code que j'utilise pour obtenir le décalage
timezoneId est l'identifiant du fuseau horaire de l'utilisateur (tel que EST).
la source
java.time
L'approche moderne utilise les classes java.time qui ont remplacé les anciennes classes de date-heure gênantes fournies avec les versions les plus anciennes de Java.
La
java.sql.Timestamp
classe est l'une de ces classes héritées. Ne sont plus nécessaires. À la place, utilisezInstant
ou d'autres classes java.time directement avec votre base de données en utilisant JDBC 4.2 et versions ultérieures.La
Instant
classe représente un moment sur la chronologie en UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).Si vous devez interagir avec un existant
Timestamp
, convertissez immédiatement en java.time via les nouvelles méthodes de conversion ajoutées aux anciennes classes.Pour ajuster dans un autre fuseau horaire, spécifiez le fuseau horaire en tant
ZoneId
qu'objet. Indiquez un nom de fuseau horaire approprié dans le formatcontinent/region
, tels queAmerica/Montreal
,Africa/Casablanca
ouPacific/Auckland
. N'utilisez jamais les pseudo-zones de 3 à 4 lettres telles queEST
ouIST
car ce ne sont pas de vrais fuseaux horaires, non standardisés et même pas uniques (!).Appliquer au
Instant
pour produire unZonedDateTime
objet.Pour générer une chaîne à afficher pour l'utilisateur, recherchez Stack Overflow pour
DateTimeFormatter
trouver de nombreuses discussions et exemples.Votre question consiste vraiment à aller dans l'autre sens, de la saisie des données utilisateur aux objets date-heure. Il est généralement préférable de diviser votre saisie de données en deux parties, une date et une heure.
Votre question n'est pas claire. Voulez-vous interpréter la date et l'heure entrées par l'utilisateur comme étant en UTC? Ou dans un autre fuseau horaire?
Si vous vouliez dire UTC, créez un
OffsetDateTime
avec un décalage en utilisant la constante pour UTC,ZoneOffset.UTC
.Si vous vouliez dire un autre fuseau horaire, combinez-le avec un objet de fuseau horaire, a
ZoneId
. Mais quel fuseau horaire? Vous pouvez détecter un fuseau horaire par défaut. Ou, si critique, vous devez confirmer avec l'utilisateur pour être certain de son intention.Pour obtenir un objet plus simple qui est toujours en UTC par définition, extrayez un fichier
Instant
.…ou…
Envoyez à votre base de données.
À propos de java.time
Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que
java.util.Date
,Calendar
, etSimpleDateFormat
.Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes java.time .
Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .
Où obtenir les classes java.time?
Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels futurs ajouts à java.time. Vous trouverez peut - être des classes utiles ici, comme
Interval
,YearWeek
,YearQuarter
et plus .la source