Heure actuelle en microsecondes en Java

Sur un système Unix, existe-t-il un moyen d’obtenir un horodatage avec une précision de niveau microseconde en Java? Quelque chose comme la fonction gettimeofday de gettimeofday

Non, Java n’a pas cette capacité.

Il a System.nanoTime (), mais cela donne juste un décalage par rapport à une heure déjà connue. Ainsi, même si vous ne pouvez pas prendre le nombre absolu, vous pouvez l’utiliser pour mesurer la précision en nanosecondes (ou plus).

Notez que JavaDoc indique que si cela fournit une précision à la nanoseconde, cela ne signifie pas une précision à la nanoseconde. Donc, prenez un module suffisamment grand de la valeur de retour.

Vous pouvez utiliser System.nanoTime() :

 long start = System.nanoTime(); // do stuff long end = System.nanoTime(); long microseconds = (end - start) / 1000; 

obtenir le temps en nanosecondes mais c’est une mesure ssortingctement relative. Cela n’a pas de sens absolu. Ce n’est utile que pour comparer à d’autres temps nano afin de mesurer combien de temps il a fallu faire.

tl; dr

Java 9 et versions ultérieures: Résolution allant jusqu’à nanosecondes lors de la capture du moment actuel. C’est 9 chiffres de la fraction décimale.

 Instant.now() 

2017-12-23T12: 34: 56.123456789Z

Pour limiter à microsecondes, tronquer.

 Instant.now().truncatedTo( ChronoUnit.MICROSECONDS ); 

2017-12-23T12: 34: 56.123456Z

Détails

Les autres réponses sont quelque peu obsolètes à cause de Java 8.

java.time

Java 8 et les versions ultérieures sont livrées avec le framework java.time . Ces nouvelles classes supplantent les classes de date / heure gênantes et défectueuses livrées avec les premières versions de Java telles que java.util.Date/.Calendar et java.text.SimpleDateFormat. Le framework est défini par JSR 310, inspiré par Joda-Time , étendu par le projet ThreeTen-Extra.

Les classes de java.time se résolvent en nanosecondes , beaucoup plus fines que les millisecondes utilisées par les anciennes classes date-heure et par Joda-Time. Et plus fine que les microsecondes posées dans la question.

entrer la description de l'image ici

Mise en œuvre de l’ Clock

Alors que les classes java.time prennent en charge les données représentant des valeurs en nanosecondes, les classes ne génèrent pas encore de valeurs en nanosecondes. Les méthodes now() utilisent la même implémentation d’horloge que les anciennes classes date-heure, System.currentTimeMillis() . Nous avons la nouvelle interface Clock dans java.time mais l’implémentation de cette interface est la même horloge millisecondes.

Vous pouvez donc formater la représentation textuelle du résultat de ZonedDateTime.now( ZoneId.of( "America/Montreal" ) ) pour voir neuf chiffres d’une seconde fractionnaire, mais seuls les trois premiers chiffres auront des nombres comme ceci:

2017-12-23T12:34:56.789000000Z

Nouvelle horloge en Java 9

Les implémentations OpenJDK et Oracle de Java 9 ont une nouvelle implémentation d’ Clock par défaut avec une granularité plus fine, jusqu’à la capacité nanoseconde complète des classes java.time.

Voir le problème OpenJDK, Augmentez la précision de l’implémentation de java.time.Clock.systemUTC () . Ce problème a été mis en œuvre avec succès.

2017-12-23T12:34:56.123456789Z

Sur un MacBook Pro (Retina, 15 pouces, fin 2013) avec macOS Sierra, j’obtiens l’instant actuel en microsecondes (jusqu’à six chiffres de fraction décimale).

2017-12-23T12:34:56.123456Z

Horloge de matériel

N’oubliez pas que même avec une nouvelle implémentation d’ Clock plus fine, vos résultats peuvent varier d’un ordinateur à l’autre. Java dépend de l’horloge du matériel informatique sous-jacent pour connaître le moment actuel.

  • La résolution des horloges matérielles est très variable. Par exemple, si l’horloge matérielle d’un ordinateur particulier ne prend en charge que la granularité des microsecondes , toutes les valeurs de date / heure générées n’auront que six chiffres de seconde fractionnaire, les trois derniers chiffres étant des zéros.
  • La précision des horloges matérielles est très variable. Tout simplement parce qu’une horloge génère une valeur avec plusieurs chiffres de fraction décimale de seconde, ces chiffres peuvent être inexacts, juste des approximations, à la différence de l’heure réelle, comme cela pourrait être lu à partir d’une horloge atomique . En d’autres termes, le simple fait de voir un groupe de chiffres à droite de la marque décimale ne signifie pas que vous pouvez vous fier au temps écoulé entre ces lectures pour être fidèle à ce degré infime.

Comme d’autres affiches déjà indiqué; votre horloge système n’est probablement pas synchronisée en microsecondes par rapport à l’heure mondiale réelle. Néanmoins, les horodatages de précision en microsecondes sont utiles en tant qu’hybrides pour indiquer à la fois l’heure locale du mur et la mesure / le profil de la durée des choses.

J’étiquette tous les événements / messages écrits dans un fichier journal en utilisant des horodatages tels que “2012-10-21 19: 13: 45.267128”. Celles-ci véhiculent les deux quand cela s’est produit (temps “mur”), et peuvent également être utilisées pour mesurer la durée entre cet événement et l’événement suivant dans le fichier journal (différence relative en microsecondes).

Pour ce faire, vous devez lier System.currentTimeMillis () avec System.nanoTime () et travailler exclusivement avec System.nanoTime () à partir de ce moment. Exemple de code:

 /** * Class to generate timestamps with microsecond precision * For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128" */ public enum MicroTimestamp { INSTANCE ; private long startDate ; private long startNanoseconds ; private SimpleDateFormat dateFormat ; private MicroTimestamp() { this.startDate = System.currentTimeMillis() ; this.startNanoseconds = System.nanoTime() ; this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ; } public Ssortingng get() { long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ; long date = this.startDate + (microSeconds/1000) ; return this.dateFormat.format(date) + Ssortingng.format("%03d", microSeconds % 1000) ; } } 

Si vous êtes intéressé par Linux: Si vous extrayez le code source dans “currentTimeMillis ()”, vous verrez que, sous Linux, si vous appelez cette méthode, elle récupère une microseconde. Cependant, Java tronque alors les microsecondes et vous renvoie des millisecondes. Ceci est dû en partie au fait que Java doit être multi-plateforme, de sorte que fournir des méthodes spécifiques à Linux était un grand pas en arrière (souvenez-vous de cette prise en charge de la liaison lente à partir de 1.6?). C’est aussi parce que, bien que votre horloge puisse vous restituer des microsecondes sous Linux, cela ne signifie pas nécessairement que cela vous permettra de vérifier l’heure. Au niveau de la microseconde, vous devez savoir que NTP ne réaligne pas votre temps et que votre horloge n’a pas trop dérive pendant les appels de méthode.

Cela signifie qu’en théorie, sous Linux, vous pouvez écrire un wrapper JNI identique à celui du package System, mais ne pas tronquer les microsecondes.

une solution “rapide et sale” avec laquelle j’ai finalement abouti:

 TimeUnit.NANOSECONDS.toMicros(System.nanoTime()); 

METTRE À JOUR:

Au départ, je suis allé avec System.nanoTime, mais j’ai découvert qu’il ne fallait l’utiliser que pour le temps écoulé, j’ai finalement changé mon code pour travailler avec des millisecondes ou à certains endroits:

 TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()); 

mais cela ne fera qu’append des zéros à la fin de la valeur (micros = millis * 1000)

A laissé cette réponse ici comme un “panneau d’avertissement” au cas où quelqu’un d’autre penserait à nanoTime 🙂

Java prend en charge les microsecondes via TimeUnit enum.

Voici le doc java: Enum TimeUnit

Vous pouvez obtenir des microsecondes dans Java de cette façon:

 long microsenconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()); 

Vous pouvez également convertir des microsecondes à d’autres unités de temps, par exemple:

 long seconds = TimeUnit.MICROSECONDS.toSeconds(microsenconds); 

Si vous avez l’intention de l’utiliser pour le système en temps réel, java n’est peut-être pas le meilleur choix pour obtenir l’horodatage. Mais si vous allez utiliser si pour une clé unique, alors la réponse de Jason Smith fera assez. Mais juste au cas où, pour anticiper que 2 éléments obtiennent le même horodatage (il est possible que ces 2 aient été traités presque simultanément), vous pouvez effectuer une boucle jusqu’à ce que le dernier horodatage ne soit pas égal à l’horodatage actuel.

 Ssortingng timestamp = new Ssortingng(); do { timestamp = Ssortingng.valueOf(MicroTimestamp.INSTANCE.get()); item.setTimestamp(timestamp); } while(lasttimestamp.equals(timestamp)); lasttimestamp = item.getTimestamp(); 

Vous pourriez peut-être créer un composant qui détermine le décalage entre System.nanoTime () et System.currentTimeMillis () et obtenir efficacement des nanosecondes depuis l’époque.

 public class TimerImpl implements Timer { private final long offset; private static long calculateOffset() { final long nano = System.nanoTime(); final long nanoFromMilli = System.currentTimeMillis() * 1_000_000; return nanoFromMilli - nano; } public TimerImpl() { final int count = 500; BigDecimal offsetSum = BigDecimal.ZERO; for (int i = 0; i < count; i++) { offsetSum = offsetSum.add(BigDecimal.valueOf(calculateOffset())); } offset = (offsetSum.divide(BigDecimal.valueOf(count))).longValue(); } public long nowNano() { return offset + System.nanoTime(); } public long nowMicro() { return (offset + System.nanoTime()) / 1000; } public long nowMilli() { return System.currentTimeMillis(); } } 

Le test suivant produit des résultats assez bons sur ma machine.

  final Timer timer = new TimerImpl(); while (true) { System.out.println(timer.nowNano()); System.out.println(timer.nowMilli()); } 

La différence semble osciller entre +3ms. Je suppose que l'on pourrait modifier le calcul du décalage un peu plus.

 1495065607202174413 1495065607203 1495065607202177574 1495065607203 ... 1495065607372205730 1495065607370 1495065607372208890 1495065607370 ... 

Voici un exemple de création d’un horodatage actuel UnsignedLong:

 UnsignedLong current = new UnsignedLong(new Timestamp(new Date().getTime()).getTime());