Comment obtenir des millisecondes à partir de LocalDateTime dans Java 8

285

Je me demande s'il y a un moyen de millisecondes en cours depuis 01/01/1970 (époque) en utilisant la nouvelle LocalDate, LocalTimeou des LocalDateTimeclasses de Java 8.

La voie connue est ci-dessous:

long currentMilliseconds = new Date().getTime();

ou

long currentMilliseconds = System.currentTimeMillis();
George Siggouroglou
la source
6
Qu'est-ce qui ne va pas System.currentTimeMillis()?
Dawood ibn Kareem
16
@DavidWallace Il essaie d'obtenir l'heure d'une date, pas l'heure actuelle?
Anubian Noob
2
"... un moyen d'obtenir les millisecondes actuelles ..."
Dawood ibn Kareem
millisecondes comptant du 1-1-1970. Je me demandais s'il existe une méthode pour les faire utiliser les nouvelles classes de Java 8 LocalDate, LocalTime et LocalDateTime, car je n'en ai pas trouvé.
George Siggouroglou
1
D'après ce que je comprends de l'objectif de ces cours, c'est une compréhension du temps "axée sur l'homme", et elle currentTimeMillisserait sans objet dans ce contexte. Pensez Calendrier + Horloge murale avec une très bonne précision, sans souci de fuseaux horaires et de localité. Il n'y a donc aucun moyen de revenir à "UTC Time" à partir d'un LocalTime
Gus

Réponses:

325

Je ne suis pas tout à fait sûr de ce que vous entendez par "millisecondes actuelles" mais je suppose que c'est le nombre de millisecondes depuis "l'époque", à savoir minuit, le 1er janvier 1970 UTC.

Si vous voulez trouver le nombre de millisecondes depuis l'époque en ce moment, utilisez-le System.currentTimeMillis()comme l' a souligné Noub anubien . Si tel est le cas, il n'y a aucune raison d'utiliser l'une des nouvelles API java.time pour ce faire.

Cependant, vous possédez peut-être déjà un LocalDateTimeobjet similaire de quelque part et vous souhaitez le convertir en millisecondes depuis l'époque. Il n'est pas possible de le faire directement, car la LocalDateTimefamille d'objets n'a aucune idée de leur fuseau horaire. Ainsi, les informations de fuseau horaire doivent être fournies pour trouver l'heure par rapport à l'époque, qui est en UTC.

Supposons que vous en ayez un LocalDateTimecomme ça:

LocalDateTime ldt = LocalDateTime.of(2014, 5, 29, 18, 41, 16);

Vous devez appliquer les informations de fuseau horaire, donnant un ZonedDateTime. Je suis dans le même fuseau horaire que Los Angeles, donc je ferais quelque chose comme ça:

ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles"));

Bien sûr, cela fait des hypothèses sur le fuseau horaire. Et il y a des cas marginaux qui peuvent se produire, par exemple, si l'heure locale arrive à nommer une heure proche de la transition de l'heure d'été (heure d'été). Mettons cela de côté, mais sachez que ces cas existent.

Quoi qu'il en soit, si vous pouvez obtenir un valide ZonedDateTime, vous pouvez le convertir en nombre de millisecondes depuis l'époque, comme ceci:

long millis = zdt.toInstant().toEpochMilli();
Stuart Marks
la source
5
Notez que ZonedDateTime déjà a la getEpochSecondméthode (par défaut ChronoZonedDateTime ). Pas besoin de Instant.
mabi
14
Bien sûr, si vous n'avez besoin que de secondes, pas de millisecondes.
Stuart Marks
1
Eh bien, je manque de précision: ZonedDateTimea également Instantde getNanola méthode, de sorte que vous ne seriez pas en mesure de remplacer tout simplement instavec zdtvotre exemple?
mabi
18
Évitez les calculs sur les nanos en utilisant zdt.get (ChronoField.MILLI_OF_SECOND). Évitez tous les calculs en utilisant zdt.toInstant (). ToEpochMilli ()
JodaStephen
1
Quoi qu'il en soit, puisque vous et @walen avez commenté, j'ai décidé de supprimer mes messages d'origine maintenant, pour éviter d'induire les gens en erreur.
Per Lundberg
81

Ce que je fais, je ne spécifie pas de fuseau horaire,

System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("ctm " + System.currentTimeMillis());

donne

ldt 1424812121078 
ctm 1424812121281

Comme vous pouvez le voir, les chiffres sont les mêmes, sauf pour un petit temps d'exécution.

Au cas où vous n'aimeriez pas System.currentTimeMillis, utilisez Instant.now().toEpochMilli()

Brian
la source
3
Non, Epoch est relative à UTC mais vous obtenez l'heure actuelle de votre zone locale.
Rafael Membrives
2
@ ChristofferHammarström le nombre de millisecondes qui se sont écoulées depuis l'époque est un fait indépendant du fuseau horaire. C'est la même quantité de millisecondes, peu importe l'heure à laquelle vous l'appelez. Les deux résultats sont différents car la machine de brian a mis 203 millisecondes pour exécuter la deuxième commande.
Fletch
Est-il correct d'utiliser UTC lorsque l'utilisateur peut être dans un fuseau horaire différent
GilbertS
2
@GilbertS vous ne devriez probablement jamais utiliser ce code exact, utilisez l'API comme prévu. La date-heure doit toujours être UTC lorsqu'elle est stockée sur un ordinateur ou transmise à un autre utilisateur. Il doit généralement être présenté à l'utilisateur comme une heure locale en utilisant ses propres paramètres de fuseau horaire.
brian
20

Pour éviter ZoneId, vous pouvez faire:

LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0);

System.out.println("Initial Epoch (TimeInMillis): " + date.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());

Obtenir 0 comme valeur, c'est vrai!

Dani
la source
8
ZoneOffset.ofTotalSeconds(0)c'est la même chose queZoneOffset.UTC
Anton Novopashin
1
Oui, c'était moi qui votait le commentaire de @ AntonNovopashin. Puisque vous aviez besoin de l'UTC, vous allez bien (vous voudrez peut-être le mentionner dans la réponse). BTW ZoneOffsetest une sous-classe de ZoneId, donc je ne dirais pas exactement que vous l'avez évité, mais tant que vous êtes heureux…
Ole VV
Mon premier commentaire était un peu dur, mais n'était pas censé être offensant. Vous vous êtes offusqué. Je suis désolé. Je l'ai supprimé. Permettez-moi de demander le contraire: quelle pourrait être notre raison de vouloir éviter ZoneId?
Ole VV
@ OleV.V Est-il correct d'utiliser UTC. Ce n'est pas seulement pour les personnes vivant dans le fuseau horaire UTC.
GilbertS
1
@GilbertS Je pense que personne ne vit dans le fuseau horaire UTC. L'utilisation de l'UTC pour les heures qui sont utilisées sur plusieurs fuseaux horaires est recommandée comme bonne pratique. Voir par exemple Java Best Practice for Manipulation / Storage Date for Geographically Diverse Users . Ou peut-être que je n'ai pas compris votre question?
Ole VV
15

Depuis Java 8, vous pouvez appeler java.time.Instant.toEpochMilli().

Par exemple l'appel

final long currentTimeJava8 = Instant.now().toEpochMilli();

vous donne les mêmes résultats que

final long currentTimeJava1 = System.currentTimeMillis();
Marteng
la source
1
"vous donne les mêmes résultats que" ... mais prend plus de puissance CPU et sollicite beaucoup plus le garbage collector.
VasiliNovikov
1
J'aimerais voir ce qui précède quantifié (en particulier pour une utilisation normale - par exemple pas pour certaines applications en temps réel critiques pour les performances ...)
Brian Agnew
11

Vous pouvez java.sql.Timestampégalement utiliser pour obtenir des millisecondes.

LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);
Nalam
la source
Vous ignorez le besoin crucial d'un fuseau horaire. Je ne recommande pas de le faire de cette façon. ÉgalementTimestamp classe est dépassée depuis longtemps et remplie de problèmes de conception, je préfère donc l'éviter, surtout lorsque nous pouvons utiliser les classes de la java.timemême manière LocalDateTime.
Ole VV
@ OleV.V. Juste curieux de connaître les problèmes de conception deTimestamp , pouvez-vous partager un article à ce sujet? Cela m'aide également à éviter d'utiliser Timestampmon code. Merci!
Nalam
1
Bref, il est implémenté comme une sous-classe de Datemais ne peut souvent pas être traité comme un Date. La plupart des méthodes héritées de Dateet un constructeur sont obsolètes. Sa toStringméthode utilise le fuseau horaire de la JVM, ce qui en déroute beaucoup car le même Timestampest imprimé différemment sur différents ordinateurs ( exemple ).
Ole VV
C'est parfait pour les tests unitaires. Il suffit de remplacer le maintenant parLocalDate.of(year, month, day)
G_V
Cela devrait être la réponse acceptée pour contourner les valeurs "toujours UTC".
LeYAUable
9

Pour obtenir l'heure actuelle en millisecondes (depuis l'époque), utilisez System.currentTimeMillis().

Anubian Noob
la source
3

Si vous avez une horloge Java 8, vous pouvez l'utiliser clock.millis()(bien qu'il vous recommande d'utiliserclock.instant() pour obtenir un instantané Java 8, car il est plus précis).

Pourquoi utiliseriez-vous une horloge Java 8? Donc, dans votre framework DI, vous pouvez créer un bean Clock:

@Bean
public Clock getClock() {
    return Clock.systemUTC();
}

puis dans vos tests, vous pouvez facilement vous moquer de lui:

@MockBean private Clock clock;

ou vous pouvez avoir un bean différent:

@Bean
public Clock getClock() {
    return Clock.fixed(instant, zone);
}

ce qui aide à des tests qui affirment des dates et des heures incommensurablement.

JeeBee
la source
1
  default LocalDateTime getDateFromLong(long timestamp) {
    try {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC);
    } catch (DateTimeException tdException) {
      //  throw new 
    }
}

default Long getLongFromDateTime(LocalDateTime dateTime) {
    return dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli();
}
Mohamed.Abdo
la source
0

Pourquoi personne n'a mentionné la méthode LocalDateTime.toEpochSecond():

LocalDateTime localDateTime = ... // whatever e.g. LocalDateTime.now()
long time2epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);

Cela semble beaucoup plus court que beaucoup de réponses suggérées ci-dessus ...

maxxyme
la source
C'est ce que je cherchais. Cette réponse acceptée me donnait les testaments.
Brill Pappin
Acceptez sa seule version disponible dans l'API 26: {
Brill Pappin
1
Parce que cela ne donne que quelques secondes. C'est bizarre qu'il n'y ait pas de toEpochMilliméthode, compte tenu du fait que vous pouvez spécifier même des nanosecondes dans LocalDateTime: il y a une méthode LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond).
izogfif