128 votes

Conversion de Long en Date en Java retourne 1970

J'ai une liste avec de longues valeurs (par exemple : 1220227200, 1220832000, 1221436800...) que j'ai téléchargées à partir d'un service web. Je dois les convertir en dates. Malheureusement, de cette façon, par exemple :

Date d = new Date(1220227200);

retourne le 1er janvier 1970. Est-ce que quelqu'un sait un autre moyen de le convertir correctement ?

0 votes

Pourriez-vous dire quelles valeurs vous attendez? La question des secondes/milliseconds peut être valide, mais 1220227200 n'est pas le 1/1/1970. Il semble que vous passiez 0 au constructeur. Un peu plus de code pourrait aider.

1 votes

@mmmiki - vous devriez accepter une réponse

0 votes

Il renvoie le 15 janv. 1970, ici, et non le 1er janv.

179voto

BalusC Points 498232

Le constructeur de java.util.Date prenant le date en argument de type long interprète l'argument en millisecondes, pas en secondes.

Paramètres: date - les millisecondes depuis le 1er janvier 1970, 00:00:00 GMT.

Votre valeur est en secondes, vous devez donc la convertir en millisecondes. Vous pouvez soit le multiplier par 1000 soit utiliser l'assistant TimeUnit.

Date date = new Date(TimeUnit.SECONDS.toMillis(1220227200));

Cela affiche ici:

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

Ce qui équivaut au 1er septembre 2008 à 00:00 UTC.

Dans le cas où vous êtes déjà sur Java 8 ou plus récent, il est préférable d'utiliser Instant#ofEpochSecond() à la place. De cette façon, vous n'avez pas besoin de convertir les secondes en millisecondes même s'il existe aussi une méthode Instant#ofEpochMilli().

Instant instant = Instant.ofEpochSecond(1220227200);

Cela affiche ici:

2008-09-01T00:00:00Z

24 votes

Ou utilisez alternativement Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L)); pour une solution plus propre et moins magique.

73voto

Basil Bourque Points 8938

Tl;dr

java.time.Instant                    // Représente un moment tel qu'il est vu en UTC. En interne, un comptage de nanosecondes depuis 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Passe un comptage de secondes entières depuis la même référence d'époque de 1970-01-01T00:00Z.

Connaissez Vos Données

Les gens utilisent diverses précisions pour suivre le temps en tant que nombre depuis une époque. Donc lorsque vous obtenez des nombres à interpréter comme un comptage depuis une époque, vous devez déterminer :

  • Quelle époque?
    De nombreuses époques ont été utilisées dans divers systèmes. Couramment utilisée est l'époque POSIX/Unix, où l'époque est le premier moment de 1970 en UTC. Mais vous ne devriez pas supposer cette époque.
  • Quelle précision?
    Parlons-nous de secondes, de millisecondes, de microsecondes ou de nanosecondes depuis l'époque?
  • Quel fuseau horaire?
    En général, un comptage depuis l'époque est enregistré dans le fuseau horaire UTC/GMT, c'est-à-dire, n'a aucun décalage de fuseau horaire du tout. Mais parfois, lorsqu'il s'agit de programmeurs inexpérimentés ou ignorants de la date et de l'heure, il peut y avoir un fuseau horaire implicite.

Dans votre cas, comme d'autres l'ont noté, il semble que vous ayez reçu des secondes depuis l'époque Unix. Mais vous passez ces secondes à un constructeur qui attend des millisecondes. La solution est donc de multiplier par 1 000.

Leçons apprises :

  • Déterminez, ne supposez pas, la signification des données reçues.
  • Lisez la documentation.

Graphique montrant diverses granularités de résolution dans les systèmes de date-heure incluant des secondes entières, des millisecondes, des microsecondes et des nanosecondes.

Vos Données

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

Joda-Time

Les classes java.util.Date et .Calendar fournies avec Java sont notoirement problématiques. Évitez-les. Utilisez plutôt la bibliothèque Joda-Time ou le nouveau package java.time inclus dans Java 8 (et inspiré par Joda-Time).

À noter que contrairement à j.u.Date, un DateTime dans Joda-Time connaît vraiment son propre fuseau horaire attribué. Ainsi dans le code Joda-Time 2.4 vu ci-dessous en exemple, notez que nous parsions d'abord les millisecondes en utilisant l'hypothèse par défaut de l'UTC. Ensuite, deuxièmement, nous attribuons un fuseau horaire de Paris pour ajuster. Même moment dans la chronologie de l'Univers, mais différente heure affichée. Pour une démonstration, nous ajustons de nouveau, vers UTC. Il est presque toujours préférable de spécifier explicitement votre fuseau horaire désiré/attendu plutôt que de se fier à un paramètre par défaut implicite (souvent à l'origine des problèmes dans le travail sur les dates et heures).

Nous avons besoin de millisecondes pour construire un DateTime. Donc prenez votre entrée de secondes, et multipliez par mille. Notez que le résultat doit être un entier long de 64 bits long car nous aurions un dépassement d'un entier de 32 bits int.

long entrée = 1 220 227 200L;  // Notez le "L" ajouté aux littéraux entiers longs.
long millisecondes = ( entrée * 1 000L ); // Utilisez un "long", pas l'habituel "int". Notez le "L" ajouté.

Alimentez ce comptage de millisecondes au constructeur. Ce constructeur particulier suppose que le comptage est depuis l'époque Unix de 1970. Donc ajustez le fuseau horaire selon vos besoins, après la construction.

Utilisez les noms de bons fuseaux horaires, une combinaison de continent et ville/région. Ne jamais utiliser des codes à 3 ou 4 lettres comme EST car ils ne sont ni normalisés ni uniques.

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

Pour une démonstration, ajustez de nouveau le fuseau horaire.

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

Impression sur la console. Notez comment 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 );

À l'exécution.

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 créateurs de Joda-Time nous ont demandé de migrer vers son remplacement, le cadre java.time dès que cela est pratique. Bien que Joda-Time continue d'être activement soutenu, tout développement futur se fera sur les classes java.time et leurs extensions dans le projet ThreeTen-Extra.

Le cadre java-time est défini par le JSR 310 et intégré dans Java 8 et ultérieur. Les classes java.time ont été rétroportées vers Java 6 & 7 sur le projet ThreeTen-Backport et vers Android dans le projet ThreeTenABP.

Un Instant est un moment sur la ligne de temps en 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 décalage par rapport à l'UTC à un ZoneOffset pour obtenir un OffsetDateTime.

Mieux encore, si vous le savez, appliquez un ZoneId de fuseau horaire pour obtenir un ZonedDateTime.

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

Tableau de tous les types de date-heure en Java, modernes et hérités

1 votes

Salut mon pote. Super explication. Je recevais un nouveau DateTime() de 1970 quand j'ai réalisé que je le donnais en secondes et qu'il était nécessaire en millisecondes

45voto

Codemwnci Points 28817

Il semble que vos longs soient des secondes et non des millisecondes. Le constructeur de Date prend le temps en millisecondes, donc

Date d = new Date(timeInSeconds * 1000);

4 votes

@f1sh: Je n'ai pas voté négativement, mais la réponse originale était différente. Il l'a éditée dans un délai de grâce de 5 minutes.

0 votes

Merci pour la clarification. C'est le seul inconvénient que SO a... :-/

12voto

Marlon Points 1

Seulement définir l'heure en millisecondes sur l'objet Calendrier

Calendrier c = Calendrier.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));
// obtenir la date
System.out.println(c.getTime());

9voto

Magnus Winter Points 703

Il s'agit probablement de balises temporelles en secondes et non en millisecondes, ce qui est requis pour le constructeur java new Date(long). Il suffit de les multiplier par 1000 et vous devriez être bon.

23 votes

Plus précisément 30000 millisecondes trop lent

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