web-dev-qa-db-fra.com

La conversion de long en date dans Java renvoie 1970

J'ai une liste avec des valeurs longues (par exemple: 1220227200, 1220832000, 1221436800 ...) que j'ai téléchargées depuis le service Web. Je dois le convertir en dates. Malheureusement de cette façon, par exemple:

Date d = new Date(1220227200);

renvoie le 1er janvier 1970. Quelqu'un connaît-il un autre moyen de le convertir correctement?

93
mmmiki

Le constructeur Date (cliquez sur le lien!) Accepte le temps long dans millisecondes, pas les secondes. Vous devez le multiplier par 1 000 et vous assurer de le fournir sous la forme long.

Date d = new Date(1220227200L * 1000);

Cela montre ici

Dimanche 31 août 20:00:00 GMT-04:00 2008

136
BalusC

tl; dr

Instant.ofEpochSecond( 1_220_227_200L )

Connaissez vos données

Les gens utilisent diverses précisions dans le suivi du temps en tant que nombre depuis Epoch . Ainsi, lorsque vous obtenez des nombres à interpréter comme un compte depuis une époque, vous devez déterminer:

  • Quelle époque?
    Plusieurs dates ont été utilisées dans divers systèmes. On utilise couramment heure POSIX/Unix , où l’époque est le premier moment de 1970 en UTC. Mais vous ne devriez pas assumer cette époque.
  • Quelle précision?
    Parlons-nous de secondes, millisecondes _, _ { microsecondes , ou nanosecondes depuis l'époque?
  • Quel fuseau horaire?
    Habituellement, un compte depuis Epoch est dans UTC /fuseau horaire GMT, c'est-à-dire qu'il n'a aucun décalage de fuseau horaire. Mais parfois, lorsque des programmeurs inexpérimentés ou ignorants de la date-heure sont impliqués, il peut y avoir un fuseau horaire implicite.

Dans votre cas, comme d’autres l’ont noté, il semble que vous ayez eu quelques secondes depuis l’époque Unix. Mais vous transmettez ces secondes à un constructeur qui attend des millisecondes. La solution consiste donc à multiplier par 1 000. 

Leçons apprises:

  • Déterminez, ne supposez pas, la signification des données reçues.
  • Lire le doc .

Graph showing various granularities of resolution in date-time systems including whole seconds, milliseconds, microseconds, and nanoseconds.

Vos données

Vos données semblent être en secondes entières. Si nous supposons une époque du début de 1970 et si nous supposons le fuseau horaire UTC, alors 1,220,227,200 est le premier instant du premier jour de septembre 2008.

Joda-Time

Les classes Java.util.Date et .Calendar fournies avec Java sont notoirement gênantes. Évite-les. Utilisez à la place la bibliothèque Joda-Time _ ou le nouveau package package Java.time fourni avec Java 8 (et inspiré de Joda-Time).

Notez que contrairement à j.u.Date, un DateTime dans Joda-Time connaît réellement son propre fuseau horaire }. Ainsi, dans l'exemple de code Joda-Time 2.4 ci-dessous, notez que nous analysons d'abord les millisecondes en utilisant l'hypothèse par défaut de l'UTC. Ensuite, nous assignons un fuseau horaire de Paris à régler. Même moment dans la chronologie de l'univers, mais différent heure de l'horloge murale . Pour démonstration, nous ajustons à nouveau, à UTC. Il est presque toujours préférable de spécifier explicitement le fuseau horaire souhaité/attendu plutôt que de s’appuyer sur un défaut implicite (souvent la cause de problèmes dans le travail date-heure).

Il faut des millisecondes pour construire un DateTime. Alors, prenez votre entrée en secondes et multipliez-la par mille. Notez que le résultat doit être un fichier long de 64 bits, comme nous le ferions déborder d'un int de 32 bits.

long input = 1_220_227_200L;  // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".

Envoyez ce nombre de millisecondes au constructeur. Ce constructeur part du principe que le décompte provient de l’époque Unix de 1970. Ajustez donc le fuseau horaire après votre construction.

Utilisez fuseau horaire correct } _ noms, une combinaison de continent et de ville/région. N'utilisez jamais de codes de 3 ou 4 lettres tels que EST, car ils ne sont ni normalisés ni uniques.

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );

Pour démonstration, réglez à nouveau le fuseau horaire.

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );

Dump à la console. Notez en quoi la date est différente à Montréal, car le nouveau jour a commencé en Europe mais pas encore en Amérique.

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );

Quand couru.

dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00

Java.time

Les fabricants de Joda-Time nous ont demandé de migrer vers son remplacement, le framework Java.time dès que possible. Bien que Joda-Time continue à être activement pris en charge, tous les développements futurs concerneront les classes Java.time et leurs extensions dans le projet ThreeTen-Extra.

La structure Java-Time est définie par JSR 310 et intégrée à Java 8 et versions ultérieures. Les classes Java.time ont été rétroportées vers Java 6 et 7 sur le projet ThreeTen-Backport et sur Android dans le projet ThreeTenABP

Un Instant est un moment sur la ligne de temps dans UTC avec une résolution de nanosecondes. Son époque est le premier moment de 1970 en UTC.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

Appliquez un offset-par-UTC _ { ZoneOffset pour obtenir un OffsetDateTime

Mieux encore, si vous le connaissez, appliquez un fuseau horaire ZoneId pour obtenir un ZonedDateTime

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

Il semble que vos longs soient en secondes et non en millisecondes. Date constructeur prend du temps en millis, donc 

Date d = new Date(timeInSeconds * 1000);
36
Codemwnci

Ce sont probablement des horodatages en secondes et non en millisecondes qui sont requis pour le constructeur Java new Date (long). Il suffit de les multiplier par 1000 et vous devriez aller bien.

9
Magnus Winter

Définir uniquement l'heure en millièmes sur l'objet Calendrier

Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());
9
Marlon

Les valeurs longues, très probablement, correspondent à Epoch timestamps, et les valeurs sont:

1220227200 = lun, 01 sept. 2008 00:00:00 GMT

1220832000 = lun, 08 sept. 2008 00:00:00 GMT

1221436800 = Lundi, 15 septembre 2008 00:00:00 GMT

On peut convertir ces valeurs longues en Java.util.Date , en prenant en compte le fait que Java.util.Date utilise des millisecs - comme indiqué précédemment, mais avec quelques défauts - comme ceci:

// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L); 

Maintenant, pour afficher correctement la date, on peut utiliser Java.text.DateFormat comme illustré ci-après:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));

Vous trouverez ci-dessous les résultats de l'affichage de la valeur longue convertie en Java.util.Date sans À l'aide de et à l'aide de DateFormat:

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC
5
Jack G.

Essaye ça:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
4
Mohammad Namvar

1220227200 correspond au 15 janvier 1980 (et à la nouvelle date (1220227200) .toString () renvoie "jeu 15 janvier 03:57:07 CET 1970"). Si vous passez une valeur longue à une date, c'est-à-dire avant le 01/01/1970, la date du 01/01/1970 sera en fait retournée. Assurez-vous que vos valeurs ne sont pas dans cette situation (inférieure à 82800000). 

2
Shivan Dragon

Nouvelle date (nombre) renvoie une date qui est number millisecondes après le 1er janvier 1970. Il est fort probable que le format de la date n'indique pas les heures, les minutes et les secondes pour que vous sachiez qu'il est juste un peu après le 1er janvier 1970.

Vous devez analyser la date en fonction du routage d'analyse correct. Je ne sais pas ce qu'est un 1220227200, mais si c'est quelques secondes après le 1er janvier 1970, multipliez-le pour obtenir des millisecondes. Si ce n'est pas le cas, convertissez-le en millisecondes après 1970 (si vous souhaitez continuer à utiliser Java.util.Date).

0
Edwin Buck

Travaille pour moi. Vous voulez probablement le multiplier par 1000, car vous obtenez les secondes de 1970 et vous devez dépasser les millisecondes du 1er janvier 1970.

0
leifg

Essayez ceci en ajustant le format de la date.

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

Remarque: vérifiez le cycle de 24 heures ou de 12 heures.

0
abhimanyu