web-dev-qa-db-fra.com

En joda time comment convertir le fuseau horaire sans changer l'heure

J'obtiens le timestamp UTC de la base de données que je mets dans une instance JodaTime DateTime

DateTime dt = new DateTime(timestamp.getTime());

Il stocke l'heure parfaitement dire 10:00 AM Mais avec le fuseau horaire local. Par exemple, je suis dans le fuseau horaire IST qui est à +5: 30 de UTC

J'ai essayé beaucoup de choses pour changer le fuseau horaire, mais chaque chose change l'heure de 10:00 AM À autre chose en utilisant une différence de +5: 30.

Y at-il un moyen par lequel je peux changer TimeZone sans affecter le temps actuel

EDIT: Si mon heure actuelle est:

2013-09-25 11:27:34 AM      UTC

Voici le résultat lorsque j'utilise cette new DateTime(timestamp.getTime());

2013-09-25 11:27:34 AM  Asia/Kolkata

Et voici le résultat lorsque j'utilise ceci new DateTime(timestamp.getTime(), DateTimeZone.UTC);

2013-09-25 05:57:34 AM  UTC
53
Abhi

Vous pouvez utiliser la classe LocalDateTime

LocalDateTime dt = new LocalDateTime(t.getTime()); 

et convertir LocalDateTime en DateTime

DateTime dt = new LocalDateTime(timestamp.getTime()).toDateTime(DateTimeZone.UTC);  

Joda DateTime traite n'importe quel moment en millis comme "millis depuis 1970 dans le fuseau horaire actuel ". Ainsi, lorsque vous créez l'instance DateTime, celle-ci est créée avec le fuseau horaire actuel.

46
Ilya

Vous pouvez utiliser la méthode withZoneRetainFields() de DateTime pour modifier le fuseau horaire sans modifier les chiffres de la date.

45
jgm

Si votre horodatage est le: 2015-01-01T00: 00: 00.000-0500 (c'est l'heure locale [pour moi])

Essaye ça:

DateTime localDt = new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)
    .withZone(DateTimeZone.getDefault());

2014-12-31T19: 00: 00.000-05: 00

Décomposition: Cela vous donne un DateTime correspondant à votre horodatage, en spécifiant qu'il est en UTC:

new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)

2015-01-01T00: 00: 00.000Z

Cela vous donne un DateTime mais avec l'heure convertie à votre heure locale:

new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)
    .withZone(DateTimeZone.getDefault());

2014-12-31T19: 00: 00.000-05: 00

12
StvnBrkdll

Voici comment je le fais:

private DateTime convertLocalToUTC(DateTime eventDateTime) {

        // get your local timezone
        DateTimeZone localTZ = DateTimeZone.getDefault();

        // convert the input local datetime to utc  
        long eventMillsInUTCTimeZone = localTZ.convertLocalToUTC(eventDateTime.getMillis(), false);

        DateTime evenDateTimeInUTCTimeZone = new DateTime(eventMillsInUTCTimeZone);

        return evenDateTimeInUTCTimeZone.toDate();
}
2
Robert

Aucune des réponses fournies n'a réellement expliqué le problème. Le vrai problème est que les hypothèses initiales étaient incorrectes. L'horodatage de la base de données a été créé à l'aide du fuseau horaire local de la machine virtuelle Java Asia/Kolkata Et non de l'heure UTC. C'est le comportement par défaut avec JDBC, raison pour laquelle il est toujours recommandé de définir votre fuseau horaire JVM sur UTC.

Si l'horodatage de la base de données était en fait:

2013-09-25 11:27:34 AM UTC

Ou au format ISO-8601:

2013-09-25T11:27:34Z // The trailing 'Z' means UTC

Ensuite, utiliser le constructeur new DateTime(timestamp, DateTimeZone.UTC) fonctionne bien. Voir par vous-même:

Timestamp timestamp = new Timestamp(1380108454000L);
DateTime dt = new DateTime(timestamp.getTime(), DateTimeZone.UTC);
System.out.println(dt); // => 2013-09-25T11:27:34.000Z

Si vous vous demandez comment j'ai obtenu 1380108454000L, J'ai simplement utilisé les classes d'analyse syntaxique de Joda:

ISODateTimeFormat.dateTimeParser().parseMillis("2013-09-25T11:27:34Z")

Il existe également des sites Web en ligne sur lesquels vous pouvez entrer une date, une heure et un fuseau horaire. La valeur Epoch est renvoyée en millisecondes ou inversement. C'est parfois bon comme contrôle de santé mentale.

// https://www.epochconverter.com
Input: 1380108454000  Click: "Timestamp to Human Date"
Assuming that this timestamp is in milliseconds:
GMT: Wednesday, September 25, 2013 11:27:34 AM

N'oubliez pas non plus que la classe Java.sql.Timestamp Est corrélée à la classe Joda/Java 8+ Instant. Parfois, il est plus facile de convertir des classes équivalentes pour repérer des bogues comme celui-ci plus tôt.

1
nogridbag

J'ai eu le même problème. Après avoir lu cet ensemble de réponses utiles, et compte tenu de mes besoins particuliers et des objets disponibles, je l'ai résolu en utilisant un autre constructeur DateTime:

new DateTime("2012-04-23T18:25:46.511Z", DateTimeZone.UTC)
1
Ben Weaver

J'ai aussi une autre approche qui m'a été très utile. Je souhaitais que mon thread de flux de travail temporaire soit modifié en un fuseau horaire spécifique (en préservant l'heure), puis une fois le code terminé, je rétablis le fuseau horaire d'origine. Il se trouve que lorsque vous utilisez des bibliothèques Joda, vous devez:

TimeZone.setDefault(TimeZone.getTimeZone(myTempTimeZone));
TimeZone.setDefault(timeZone);

Ce n'est pas assez. Nous devons également modifier le fuseau horaire dans DateTimeZone comme suit:

@Before
public void setUp() throws Exception {
    timeZone = TimeZone.getDefault();
    dateTimeZone = DateTimeZone.getDefault();
}

@After
public void tearDown() throws Exception {
    TimeZone.setDefault(timeZone);
    DateTimeZone.setDefault(dateTimeZone);
}

@Test
public void myTest() throws Exception {
    TimeZone.setDefault(TimeZone.getTimeZone(myTempTimeZone));
    DateTimeZone.setDefault(DateTimeZone.forID(myTempTimeZone));
    //TODO
    // my code with an specific timezone conserving time
}

J'espère que cela aide aussi quelqu'un d'autre.

0
leonardo derks