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?

164
demandé sur Matt Johnson 2010-05-23 14:29:50

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");
252
répondu ZZ Coder 2016-01-08 13:22:33

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.

137
répondu Jesper 2010-05-23 14:45:21

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 avec ZoneOffset )
  • avec un fuseau horaire ( ZonedDateTime avec ZoneId )

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?

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.

61
répondu Basil Bourque 2018-09-29 19:11:32

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
60
répondu starmer 2016-01-08 13:23:55

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

6
répondu T.J. Crowder 2014-03-02 10:30:43

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 .

6
répondu diadyne 2015-05-22 18:37:00

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
0
répondu EpicPandaForce 2016-01-08 13:22:07

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);
0
répondu avisper 2018-01-18 19:31:59