Comment définir le fuseau horaire de java.util.Date?
j'ai analysé un java.util.Date
à partir d'un String
mais il définit le fuseau horaire local comme le fuseau horaire de l'objet date
.
le fuseau horaire n'est pas spécifié dans le String
duquel Date
est divisé. Je veux définir un fuseau horaire spécifique de l'objet date
.
Comment faire?
8 réponses
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");
soyez conscient que les objets java.util.Date
ne contiennent pas d'information de fuseau horaire par eux - mêmes-vous ne pouvez pas définir le fuseau horaire sur un objet Date
. La seule chose qu'un objet Date
contient est un nombre de millisecondes depuis" l'époque " - le 1er janvier 1970, 00:00:00 UTC.
comme le montre le codeur ZZ, vous définissez le fuseau horaire de l'objet DateFormat
, pour lui dire dans quel fuseau horaire vous voulez afficher la date et l'heure.
tl; dr
... divisé ... à 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 les autres réponses correctes l'ont indiqué, un java.util.La Date n'a pas de fuseau horaire † . Il représente UTC / GMT (aucun décalage de fuseau horaire). Très déroutante car sa méthode toString
applique le fuseau horaire par défaut de la JVM lors de la génération d'une représentation String.
Avoid J. U. Date
pour cette raison et bien d'autres, vous devriez éviter d'utiliser le java intégré.util.Date. & CALENDRIER & java.texte.SimpleDateFormat. Ils sont notoirement gênants.
utilisez plutôt le java.time package fourni avec Java 8 .
de java.temps
La java.les classes de temps peuvent représenter un moment sur la ligne de temps de trois façons:
- UTC (
Instant
) - avec un décalage (
OffsetDateTime
avecZoneOffset
) - avec un fuseau horaire (
ZonedDateTime
avecZoneId
)
Instant
Dans de java.temps , le bloc de base est Instant
, un moment sur la ligne du temps en UTC. Utilisez les objets Instant
pour une grande partie de votre logique d'entreprise.
Instant instant = Instant.now();
OffsetDateTime
Appliquer offset-de-UTC à régler dans certains localité horloge murale .
Appliquer 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 plus les règles pour traiter les anomalies telles que heure D'été .
appliquer un ZoneId
à un Instant
pour obtenir un ZonedDateTime
. Toujours spécifier un fuseau horaire le nom de . N'utilisez jamais 3 ou 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 de caractères d'entrée n'avait pas d'indicateur d'offset ou de zone, parse comme un LocalDateTime
.
si vous êtes certain du fuseau horaire prévu, assignez un ZoneId
pour produire un ZonedDateTime
. Voir l'exemple de code ci-dessus dans tl;dr section en haut.
Chaînes Formatées
appeler la méthode toString
sur l'une de ces trois classes pour générer une chaîne représentant la valeur date-heure dans le format standard ISO 8601 . La classe 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 les autres formats utilisez le DateTimeFormatter
de la classe. Il est généralement préférable de laisser cette classe générer des formats localisés en utilisant le langage humain et les normes culturelles attendus de l'utilisateur. Ou vous pouvez spécifier un format particulier.
à Propos de de java.heure
Le de java.time framework est construit dans Java 8 et plus tard. Ces classes supplantent le vieil héritage troublant classes de date-heure telles que java.util.Date
, Calendar
, & SimpleDateFormat
.
le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.temps classes.
pour en savoir plus, voir le Oracle Tutoriel . Et rechercher le débordement de la pile pour de nombreux exemples et explications. La spécification est JSR 310 .
vous pouvez échanger java.temps objets directement avec votre base de données. Utilisez un JDBC driver conforme à JDBC 4.2 ou plus tard. Pas besoin de Chaînes, pas besoin de classes java.sql.*
.
où obtenir Java.les classes de temps?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 , et plus tard - fait partie de L'API Java standard avec une implémentation empaquetée.
- Java 9 ajoute quelques fonctionnalités mineures et des corrections.
- Java SE 6 et Java SE 7
- la Plupart de la java.la fonctionnalité time est rétroportée à Java 6 & 7 dans ThreeTen-Backport .
- Android
- versions ultérieures des implémentations du paquet Android de java .temps classes.
- Pour plus tôt Android (<26 ans), le ThreeTenABP "1519560920 projet" s'adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP... .
Le ThreeTen-Extra le projet s'étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver ici quelques cours utiles tels que: Interval
, YearWeek
, YearQuarter
, et plus .
Joda-Time
alors que Joda-Time est encore activement maintenu, ses responsables nous ont dit de migrer vers java.le temps dès qu'il est commode. Je laisse cette section intacte comme référence, mais je suggère d'utiliser la section java.time
ci-dessus à la place.
Dans Joda-Time , un objet date-heure ( DateTime
) sait vraiment son fuseau horaire assigné. Cela signifie un décalage de UTC et par rapport aux règles et à l'historique de l'heure avancée de ce fuseau horaire et d'autres anomalies de ce genre.
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 );
appelez la méthode toString
pour générer une chaîne de caractères au format ISO 8601 .
String output = dateTimeIndia.toString();
Joda-Time offre également de riches capacités pour générer toutes sortes d'autres formats de Chaîne.
si nécessaire, vous pouvez passer de Joda-Time DateTime à un java.util.Date.
Java.util.Date date = dateTimeIndia.toDate();
rechercher StackOverflow pour" joda date " pour trouver beaucoup plus d'exemples, certains très détaillés.
† en fait il est un fuseau horaire intégré dans un java.util.Date, utilisée pour certaines fonctions internes (voir Commentaires sur ce Réponse.) Mais ce fuseau horaire interne n'est pas exposé en tant que propriété, et ne peut pas être fixé. Ce fuseau horaire interne est et non celui utilisé par la méthode toString
pour générer une représentation de chaîne de caractères de la valeur date-heure; au lieu de cela, le fuseau horaire par défaut de la JVM est appliqué à la volée. Donc, en raccourci, on dit souvent " J. U. Date has no time zone". Déroutant? Oui. Encore une raison d'éviter ces vieilles classes fatiguées.
vous pouvez aussi régler le fuseau horaire au niveau 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 la façon habituelle de gérer les fuseaux horaires en utilisant juste des classes JDK. Apache Commons a d'autres alternatives / utilités qui peuvent être utiles. Edit la note de Spong m'a rappelé que j'ai entendu de très bonnes choses au sujet de Joda-Time (bien que je ne l'ai pas utilisé moi-même).
si vous devez travailler uniquement avec les classes JDK standard, vous pouvez utiliser ceci:
/**
* Converts the given <code>date</code> from the <code>fromTimeZone</code> to the
* <code>toTimeZone</code>. 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 <code>timeZone</code> from UTC, factoring in any
* additional offset due to the time zone being in daylight savings time as of
* the given <code>date</code>.
* @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;
}
crédit va à ce post .
si quelqu'un a besoin de cela, si vous avez besoin de convertir un fuseau horaire XMLGregorianCalendar
à votre fuseau horaire actuel de UTC, alors tout ce que vous avez à faire est de définir le fuseau horaire à 0
, puis appeler toGregorianCalendar()
- il restera le même fuseau horaire, mais le Date
sait comment le convertir à la vôtre, de sorte que vous pouvez 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.toString());
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));
String dateStr = readFormat.format(date);
SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date = writeFormat.parse(dateStr);