Comment définir le fuseau horaire d’un java.util.Date?

J’ai analysé un java.util.Date partir d’une Ssortingng mais il définit le fuseau horaire local comme fuseau horaire de l’object de date .

Le fuseau horaire n’est pas spécifié dans la Ssortingng partir de laquelle la Date est analysée. Je veux définir un fuseau horaire spécifique de l’object date .

Comment puis je faire ça?

Utilisez DateFormat. Par exemple,

 SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = isoFormat.parse("2010-05-23T09:01:02"); 

Sachez que les objects java.util.Date ne contiennent aucune information de fuseau horaire – vous ne pouvez pas définir le fuseau horaire sur un object Date . La seule chose qu’un object Date contient est un nombre de millisecondes depuis le “epoch” – 1er janvier 1970, 00:00:00 UTC.

Comme ZZ Coder le montre, vous définissez le fuseau horaire sur l’object DateFormat , pour lui indiquer dans quel fuseau horaire vous souhaitez afficher la date et l’heure.

tl; dr

… Analysé… à partir d’une chaîne de caractères… le fuseau horaire n’est pas spécifié… Je veux définir un fuseau horaire spécifique

 LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse ssortingng, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`. .atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object. 

Pas de fuseau horaire dans juDate

Comme indiqué dans les autres réponses correctes, un fichier java.util.Date n’a pas de fuseau horaire . Il représente UTC / GMT (pas de décalage de fuseau horaire). Très déroutant car sa méthode toSsortingng applique le fuseau horaire par défaut de la JVM lors de la génération d’une représentation Ssortingng.

Éviter le juDate

Pour cette raison, et pour bien d’autres raisons, évitez d’utiliser java.util.Date & .Calendar & java.text.SimpleDateFormat. Ils sont notoirement ennuyeux.

Utilisez plutôt le package java.time fourni avec Java 8 . Ces nouvelles classes sont inspirées par Joda-Time , défini par JSR 310 , et étendues par le projet ThreeTen-Extra . Pour Java 6 et 7, utilisez le projet back-port, ThreeTen-Backport . Pour Android, l’adaptation de ce back-port, ThreeTenABP . Voir le didacticiel Oracle .

java.time

Les classes java.time peuvent représenter un moment de la chronologie de trois manières:

  • UTC ( Instant )
  • Avec un offset ( OffsetDateTime avec ZoneOffset )
  • Avec un fuseau horaire ( ZonedDateTime avec ZoneId )

Instant

Dans java.time , le bloc de base est Instant , un moment de la ligne temporelle en UTC. Utilisez des objects Instant pour une grande partie de votre logique métier.

 Instant instant = Instant.now(); 

OffsetDateTime

Appliquez un offset-from-UTC pour vous adapter à l’ horloge de la localité.

Appliquez un ZoneOffset pour obtenir un OffsetDateTime .

 ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" ); OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset ); 

ZonedDateTime

Mieux vaut appliquer un fuseau horaire , un décalage et les règles de traitement des anomalies telles que l’ heure d’été (DST) .

Appliquez un ZoneId à un Instant pour obtenir un ZonedDateTime . Indiquez toujours un nom de fuseau horaire approprié . Ne jamais utiliser 3-4 abréviations telles que EST ou IST qui ne sont ni uniques ni normalisées.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); 

LocalDateTime

Si la chaîne d’entrée ne LocalDateTime aucun indicateur de décalage ou de zone, LocalDateTime tant que LocalDateTime .

Si vous êtes certain du fuseau horaire prévu, affectez un ZoneId pour produire un ZonedDateTime . Voir l’exemple de code ci-dessus dans la section tl; dr en haut.

Chaînes formatées

Appelez la méthode toSsortingng sur l’une de ces trois classes pour générer une chaîne représentant la valeur date-heure au format ISO 8601 standard. La classe ZonedDateTime étend le format standard en ajoutant le nom du fuseau horaire entre crochets.

 Ssortingng outputInstant = instant.toSsortingng(); // Ex: 2011-12-03T10:15:30Z Ssortingng outputOdt = odt.toSsortingng(); // Ex: 2007-12-03T10:15:30+01:00 Ssortingng outputZdt = zdt.toSsortingng(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris] 

Pour les autres formats, utilisez la classe DateTimeFormatter . Généralement, il est préférable de laisser cette classe générer des formats localisés en utilisant le langage humain et les normes culturelles de l’utilisateur. Ou vous pouvez spécifier un format particulier.


Joda-Time

Bien que Joda-Time soit toujours activement maintenu, ses fabricants nous ont demandé de migrer vers java.time dès que cela est possible. Je laisse cette section intacte comme référence, mais je suggère d’utiliser java.time section java.time ci-dessus.

Dans Joda-Time , un object date-heure ( DateTime ) connaît vraiment son fuseau horaire. Cela signifie un décalage par rapport à l’heure UTC et aux règles et à l’historique de l’heure d’été et d’autres anomalies de ce type.

 Ssortingng input = "2014-01-02T03:04:05"; DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" ); DateTime dateTimeIndia = new DateTime( input, timeZone ); DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC ); 

Appelez la méthode toSsortingng pour générer une chaîne au format ISO 8601 .

 Ssortingng output = dateTimeIndia.toSsortingng(); 

Joda-Time offre également des fonctionnalités riches pour générer toutes sortes d’autres formats de chaîne.

Si nécessaire, vous pouvez convertir Joda-Time DateTime en java.util.Date.

 Java.util.Date date = dateTimeIndia.toDate(); 

Recherchez StackOverflow pour “joda date” pour trouver de nombreux autres exemples, certains assez détaillés.


En fait, il existe un fuseau horaire intégré à java.util.Date, utilisé pour certaines fonctions internes (voir les commentaires sur cette réponse). Mais ce fuseau horaire interne n’est pas exposé en tant que propriété et ne peut pas être défini. Ce fuseau horaire interne n’est pas celui utilisé par la méthode toSsortingng pour générer une représentation sous forme de chaîne de la valeur date-heure; au lieu de cela, le fuseau horaire par défaut actuel de la JVM est appliqué à la volée. Donc, en tant que raccourci, nous disons souvent «juDate n’a pas de fuseau horaire». Déroutant? Oui. Encore une autre raison d’éviter ces vieilles classes fatiguées.

Vous pouvez également définir le fuseau horaire au niveau de la JVM

 Date date1 = new Date(); System.out.println(date1); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); // or pass in a command line arg: -Duser.timezone="UTC" Date date2 = new Date(); System.out.println(date2); 

sortie:

 Thu Sep 05 10:11:12 EDT 2013 Thu Sep 05 14:11:12 UTC 2013 

java.util.Calendar est le moyen habituel de gérer les fuseaux horaires en utilisant uniquement les classes JDK. Apache Commons a d’autres alternatives / utilitaires qui peuvent être utiles. La note de Edit Spong m’a rappelé que j’ai entendu de très bonnes choses à propos de Joda-Time (même si je ne l’ai pas utilisé moi-même).

Si vous ne devez travailler qu’avec des classes JDK standard, vous pouvez utiliser ceci:

 /** * Converts the given date from the fromTimeZone to the * toTimeZone. Since java.util.Date has does not really store time zome * information, this actually converts the date to the date that it would be in the * other time zone. * @param date * @param fromTimeZone * @param toTimeZone * @return */ public static Date convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone) { long fromTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, fromTimeZone); long toTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, toTimeZone); return new Date(date.getTime() + (toTimeZoneOffset - fromTimeZoneOffset)); } /** * Calculates the offset of the timeZone from UTC, factoring in any * additional offset due to the time zone being in daylight savings time as of * the given date. * @param date * @param timeZone * @return */ private static long getTimeZoneUTCAndDSTOffset(Date date, TimeZone timeZone) { long timeZoneDSTOffset = 0; if(timeZone.inDaylightTime(date)) { timeZoneDSTOffset = timeZone.getDSTSavings(); } return timeZone.getRawOffset() + timeZoneDSTOffset; } 

Le crédit va à cet article .

Si vous en avez besoin, si vous avez besoin de convertir un XMLGregorianCalendar horaire XMLGregorianCalendar dans votre fuseau horaire à partir d’UTC, il vous suffit de définir le fuseau horaire sur 0 , puis d’appeler toGregorianCalendar() – le même fuseau horaire, mais la Date sait comment le convertir en votre, vous pouvez donc obtenir les données à partir de là.

 XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance() .newXMLGregorianCalendar( ((GregorianCalendar)GregorianCalendar.getInstance()); xmlStartTime.setTimezone(0); GregorianCalendar startCalendar = xmlStartTime.toGregorianCalendar(); Date startDate = startCalendar.getTime(); XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance() .newXMLGregorianCalendar(startCalendar); xmlStartTime.setHour(startDate.getHours()); xmlStartTime.setDay(startDate.getDate()); xmlStartTime.setMinute(startDate.getMinutes()); xmlStartTime.setMonth(startDate.getMonth()+1); xmlStartTime.setTimezone(-startDate.getTimezoneOffset()); xmlStartTime.setSecond(startDate.getSeconds()); xmlStartTime.setYear(startDate.getYear() + 1900); System.out.println(xmlStartTime.toSsortingng()); 

Résultat:

 2015-08-26T12:02:27.183Z 2015-08-26T14:02:27.183+02:00 

Convertissez la date en chaîne et faites-le avec SimpleDateFormat.

  SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); readFormat.setTimeZone(TimeZone.getTimeZone("GMT" + timezoneOffset)); Ssortingng dateStr = readFormat.format(date); SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); Date date = writeFormat.parse(dateStr);