256 votes

Comment définir le fuseau horaire d'une java.util.Date ?

J'ai analysé un java.util.Date d'un String mais il définit le fuseau horaire local comme étant le fuseau horaire de l'application date objet.

Le fuseau horaire n'est pas spécifié dans le String à partir de laquelle Date est analysé. Je souhaite définir un fuseau horaire spécifique pour le fichier date objet.

Comment puis-je faire cela ?

8 votes

Bien que ce ne soit pas vraiment une réponse à votre question, j'ai utilisé Joda Time après l'avoir vu mentionné ici à plusieurs reprises. Il me semble plus rationnel que les API standard, et peut faire ce genre de choses assez facilement.

2 votes

@msandiford Aujourd'hui, utiliser java.time plutôt que Joda-Time. Les Joda-Time Le projet est maintenant en mode de maintenance L'équipe conseille la migration vers l'application java.time classes. Voir Tutoriel d'Oracle .

345voto

ZZ Coder Points 36990

Utiliser 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");

6 votes

Si la date est créée à partir de la classe Calendar, vous pouvez définir le fuseau horaire pour Calendar.

27 votes

Vous pouvez définir le fuseau horaire d'un objet Calendrier, mais l'obtention d'un objet Date à l'aide de la méthode getTime() renverra un objet Date avec le fuseau horaire de l'ordinateur hôte.

1 votes

@BrDaHa a raison, vous devrez TimeZone.setDefault() avant d'appeler getTime() afin que le nouvel objet date soit dans le fuseau horaire souhaité. Dans le JDK 1.8, Calendar.getTime() appels return new Date(getTimeInMillis()); .

202voto

Jesper Points 65733

Sachez que java.util.Date ne contiennent pas d'informations sur le fuseau horaire en eux-mêmes - vous ne pouvez pas définir le fuseau horaire d'un objet Date objet. La seule chose qu'un Date contient un nombre de millisecondes depuis l'"époque" - 1er janvier 1970, 00:00:00 UTC.

Comme le montre ZZ Coder, vous pouvez régler le fuseau horaire sur la page DateFormat pour lui indiquer le fuseau horaire dans lequel vous souhaitez afficher la date et l'heure.

88 votes

Après avoir cherché sur Google, fait des expériences et des commentaires, je me suis rendu compte qu'il s'agissait d'un ajout précis et utile à la réponse - et qu'il valait la peine d'être souligné : Date sólo contient la valeur de la milliseconde . Si vous regardez la source, il n'y a pratiquement qu'une long champ appelé fastTime . Date.toString() utilise en fait un Calendar pour interpréter ce temps en millisecondes. Ainsi, l'impression d'un Date le rend apparaître ont un fuseau horaire (par défaut), ce qui suscite des questions compréhensibles sur la manière de définir ce fuseau horaire.

3 votes

Les objets Date contiennent des informations sur les fuseaux horaires. Mais il se peut que ce soit vrai, vous ne pouvez pas le changer.

3 votes

@Iwpro2, Jesper affirme (et je suis d'accord) que l'objet Date ne stocke pas de fuseau horaire. Si vous affirmez que le fuseau horaire est stocké dans java.util.Date, veuillez fournir une référence.

125voto

Basil Bourque Points 8938

Tl;dr

analysé à partir d'une chaîne 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 string, 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 j.u.Date

Comme l'indiquent les autres réponses correctes, une date 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 son toString applique le fuseau horaire par défaut de la JVM lors de la génération d'une représentation sous forme de chaîne.

Éviter j.u.Date

Pour cette raison et bien d'autres, vous devriez éviter d'utiliser les formats intégrés java.util.Date & .Calendar & java.text.SimpleDateFormat. Ils sont notoirement problématiques.

Au lieu de cela, utilisez l'option Paquet java.time regroupés avec Java 8 .

java.time

Les classes java.time peuvent représenter un moment sur la ligne du temps de trois manières :

  • UTC ( Instant )
  • Avec un décalage ( OffsetDateTime con ZoneOffset )
  • Avec un fuseau horaire ( ZonedDateTime con ZoneId )

Instant

En java.time L'élément de base est le suivant Instant , un moment sur la ligne du temps en UTC. Utiliser Instant pour une grande partie de votre logique d'entreprise.

Instant instant = Instant.now();

OffsetDateTime

Appliquer un décalage par rapport à l'UTC pour s'adapter à la situation d'une localité l'heure de l'horloge murale .

Appliquer un ZoneOffset pour obtenir un OffsetDateTime .

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

ZonedDateTime

Il est préférable d'appliquer un fuseau horaire , un décalage plus les règles de traitement des anomalies telles que Heure d'été (DST) .

Appliquer un ZoneId à un Instant pour obtenir un ZonedDateTime . Toujours spécifier un nom du fuseau horaire approprié . N'utilisez jamais les abréviations 3-4 telles que EST o IST qui ne sont ni uniques ni normalisés.

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

LocalDateTime

Si la chaîne d'entrée ne contient pas d'indicateur de décalage ou de zone, elle est analysée en tant que LocalDateTime .

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

Chaînes formatées

Appeler le toString sur l'une de ces trois classes pour générer une chaîne de caractères représentant la valeur de la date et de l'heure dans la norme ISO 8601 format. Le format ZonedDateTime étend le format standard en ajoutant le nom du fuseau horaire entre parenthèses.

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

Pour d'autres formats, utilisez la fonction DateTimeFormatter classe. Il est généralement préférable de laisser cette classe générer des formats localisés en utilisant la langue humaine et les normes culturelles attendues par l'utilisateur. Vous pouvez également spécifier un format particulier.


Table of all date-time types in Java, both modern and legacy


A propos de java.time

Les java.time est intégré à Java 8 et aux versions ultérieures. Ces classes remplacent les anciennes classes héritage les classes de date et d'heure telles que java.util.Date , Calendar , & SimpleDateFormat .

Pour en savoir plus, consultez le site Tutoriel Oracle . Vous trouverez de nombreux exemples et explications sur Stack Overflow. La spécification est JSR 310 .

Les Joda-Time Le projet, en cours d'élaboration, est en cours de réalisation. mode de maintenance conseille de migrer vers l java.time classes.

Vous pouvez échanger java.time directement avec votre base de données. L'utilisation d'un Pilote JDBC conforme à JDBC 4.2 ou plus tard. Pas besoin de ficelles, pas besoin de java.sql.* classes. Support d'Hibernate 5 et de JPA 2.2 java.time .

Où obtenir les classes java.time ?


Joda-Time

Tandis que Joda-Time est toujours activement maintenu, ses créateurs nous ont demandé de migrer vers java.time dès que possible. Je laisse cette section intacte en tant que référence, mais je suggère d'utiliser le fichier java.time ci-dessus.

En Joda-Time un objet date-heure ( DateTime ) connaît vraiment le fuseau horaire qui lui est attribué. Cela signifie qu'un décalage par rapport à UTC y les règles et l'histoire de l'heure d'été (DST) de ce fuseau horaire et d'autres anomalies de ce type.

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

Appeler le toString pour générer une chaîne de caractères en ISO 8601 format.

String output = dateTimeIndia.toString();

Joda-Time offre également de nombreuses possibilités pour générer toutes sortes d'autres formats de chaînes de caractères.

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

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

Faites une recherche sur StackOverflow avec "joda date" pour trouver de nombreux autres exemples, dont certains sont très détaillés.


† En fait, il y a est un fuseau horaire intégré dans une java.util.Date, utilisé pour certaines fonctions internes (voir les commentaires sur cette réponse). Mais ce fuseau horaire interne n'est pas exposé comme une propriété, et ne peut pas être défini. Ce fuseau horaire interne est no celui utilisé par le toString pour générer une représentation sous forme de chaîne de la valeur de la date et de l'heure ; à la place, le fuseau horaire par défaut de la JVM est appliqué à la volée. En résumé, nous disons souvent "j.u.Date n'a pas de fuseau horaire". Cela peut-il prêter à confusion ? Oui. Encore une autre raison d'éviter ces vieilles classes fatiguées.

3 votes

Le message "No Time Zone in j.u.Date" est erroné. Il y a une information sur le fuseau horaire dans j.u.Date stockée dans son fichier BaseCalendar.Date cdate si elle est définie. Jetez un coup d'œil au code source aquí . Vous ne pouvez pas définir le fuseau horaire d'un objet j.u.Date, sauf en modifiant le fuseau horaire par défaut de la JVM en appelant TimeZone.setDefault(TimeZone.getTimeZone("NEW_TIME_ZONE")); . Il existe donc un décalage de fuseau horaire que vous pouvez obtenir en appelant la méthode obsolète j.u.Date.getTimezoneOffset().

3 votes

@blquythai Correct, vous avez fait vos devoirs. Tout comme moi, qui ai déjà vu ce code source. Il y a est un fuseau horaire enterré là-dedans. Mais à toutes fins utiles, ce fuseau horaire est ignoré. Une date java.util.Date fonctionne sans fuseau horaire, en étant en fait en UTC, tout en ignorant le fuseau horaire enfoui. À l'exception du toString qui applique le fuseau horaire par défaut de la JVM, en ignorant à nouveau le fuseau horaire enterré. Par souci de concision, nous dirons qu'une java.util.Date n'a pas de fuseau horaire. Comme l'art C'est un mensonge qui dit la vérité.

0 votes

@blquythai Quant à l'appel TimeZone.setDefault , vous êtes no le réglage du fuseau horaire de l'objet java.util.Date -- l'objet Date continue d'ignorer son fuseau horaire enterré, agissant effectivement en UTC. Vous affecteriez le fuseau horaire de l'objet Date toString méthode. Le réglage par défaut modifie le fuseau horaire par défaut de la JVM, qui correspond généralement au fuseau horaire du système d'exploitation hôte. Cet appel n'est pas recommandé car elle affecte tout le code de tous les threads de toutes les applications exécutées dans cette JVM, et ce à la volée pendant leur exécution. Étant grossier et dangereux, cet appel ne devrait être envisagé qu'en dernier recours.

79voto

starmer Points 351

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

de la production :

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

1 votes

Cela m'a aidé. Le réglage du timeZone dans le SDF n'a pas fait de différence.

0 votes

Je pense qu'il est plus fiable. (+1)

26 votes

Attention : Appeler TimeZone.setDefault est plutôt radicale, car elle affecte l'ensemble de la JVM, tous les autres objets et threads. Voir cette réponse pour plus de détails, y compris des complications supplémentaires si vous utilisez un SecurityManager. Ajout d'une complication supplémentaire : Ce comportement a changé dans les différentes versions de Java, comme indiqué dans la section Cette question .

6voto

T.J. Crowder Points 285826

java.util.Calendar est la manière habituelle de gérer les fuseaux horaires en utilisant uniquement les classes du JDK. Apache Commons propose d'autres solutions/utilités qui peuvent s'avérer utiles. Éditer La note de Spong m'a rappelé que j'ai entendu de très bonnes choses à propos de Joda-Time (bien que je ne l'aie pas utilisé moi-même).

0 votes

+1 pour Joda Time. Bien qu'il ne fournisse aucune fonctionnalité supplémentaire que vous ne pourriez pas obtenir à partir de l'API Java standard (que j'ai trouvée en tout cas - heureux qu'on me démontre le contraire), Joda Time facilite certaines tâches.

2 votes

@JoshuaHutchison Joda-Time a tonnes de fonctionnalités supplémentaires. Exemple : Représentation des périodes de temps avec les classes Period , Duration y Interval . Ces travées comprennent des méthodes de comparaison telles que contains , abuts , overlap y gap . Et PeriodFormatterBuilder peut construire des phrases descriptives telles que "15 ans et 8 mois".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X