Pourquoi manque-t-il une méthode getMillis () dans les classes java.time de Java 8?

64

Java 8 a une toute nouvelle bibliothèque pour les dates et les heures dans le paquet java.time, ce qui est très appréciable pour tous ceux qui ont déjà utilisé JodaTime ou qui ont du mal à créer leurs propres méthodes d’aide au traitement des dates. Beaucoup de classes de ce paquet représentent des horodatages et ont des méthodes d'assistance comme getHour()obtenir des heures d'horodatage, des getMinute()minutes d'horodatage, des getNano()nanos d'empreintes digitales, etc.

J'ai remarqué qu'ils ne disposent pas d'une méthode appelée getMillis()pour obtenir les millis de l'horodatage. Au lieu de cela, il faudrait appeler une méthode get(ChronoField.MILLI_OF_SECOND). Pour moi, cela ressemble à une incohérence dans la bibliothèque. Quelqu'un sait-il pourquoi une telle méthode fait défaut ou que Java 8 est en cours de développement, y a-t-il une possibilité qu'il soit ajouté plus tard?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Les classes définies ici représentent les principaux concepts date-heure, notamment les instants, les durées, les dates, les heures, les fuseaux horaires et les périodes. Ils sont basés sur le système de calendrier ISO, qui est le calendrier mondial de facto qui suit les règles proleptiques grégoriennes. Toutes les classes sont immuables et thread-safe.

Chaque instance d’heure de date est composée de champs facilement mis à disposition par les API. Pour un accès de niveau inférieur aux champs, reportez-vous au java.time.temporalpackage. Chaque classe prend en charge l’impression et l’analyse de toutes sortes de dates et d’heures. Reportez-vous au java.time.formatpackage pour les options de personnalisation ...

Exemple de ce type de classe:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

Une date-heure sans fuseau horaire dans le système de calendrier ISO-8601, telle que 2007-12-03T10: 15: 30.

LocalDateTimeest un objet date-heure immuable qui représente une date-heure, souvent considérée comme année-mois-jour-heure-minute-seconde. Vous pouvez également accéder à d'autres champs de date et d'heure, tels que le jour de l'année, le jour de la semaine et la semaine de l'année. Le temps est représenté à la précision nanoseconde. Par exemple, la valeur "2 octobre 2007 à 13h45: 30.30.123456789" peut être enregistrée dans un fichier LocalDateTime...

Tarmo
la source
On dirait qu'ils veulent utiliser le polymorphisme pour résoudre un ensemble de méthodes appelées get(), plutôt que de leur donner des noms individuels et uniques. Si cela vous dérange, écrivez une classe qui hérite de la classe d'origine et mettez votre propre getMillis()méthode dans la nouvelle classe.
Robert Harvey
@RobertHarvey La plupart des classes du package java.time sont immuables et ne peuvent pas être étendues.
Assylias
2
@ RobertHarvey La question pour moi n'est pas comment puis-je résoudre ce problème. Cela a semblé faire apparaître une étrange incohérence et je me suis demandé s'il existait une explication intéressante à cela.
Tarmo
J'ai l'idée que certaines architectures / systèmes d'exploitation ne prennent pas en charge de manière fiable les millisecondes. En d'autres termes, l'heure système ne peut pas être récupérée à la milliseconde, mais à la centième ou à la déciseconde près.
Marco
Voir stackoverflow.com/a/23945792/40064 pour savoir comment faire via la Instantclasse
Wim Deblauwe

Réponses:

63

JSR-310 est basé sur des nanosecondes, pas des millisecondes. En tant que tel, l'ensemble minimal de méthodes sensibles est basé sur l'heure, les minutes, la seconde et la nanoseconde. La décision de disposer d'une base en nanosecondes était l'une des décisions initiales du projet, et une décision que je crois fermement être la bonne.

L'ajout d'une méthode pour les millis chevaucherait celle de la nanoseconde, ce qui n'est pas évident. Les utilisateurs devraient par exemple se demander si le nano-champ était du type nano-seconde ou nano-milli. L'ajout d'une méthode supplémentaire déroutante n'est pas souhaitable, elle a donc été omise. Comme indiqué, l'alternative get(MILLI_OF_SECOND)est disponible.

FWIW, je m'opposerais à l'ajout de la getMillis()méthode à l'avenir.

JodaStephen
la source
1
J'ai obtenu de très bonnes réponses à cette question, mais votre réponse est ma préférée, car elle est courte et pourtant, elle soulève toujours un très bon point et me convainc vraiment de la nécessité de cette approche. Je vous remercie.
Tarmo
12
@ s3ib si vous vérifiez le profil du répondeur , vous remarquerez également qu'il est un responsable de la spécification pour l'API même dont vous parlez. Cela fait une réponse aussi autoritaire que possible, n'est-ce pas :)
gnat
Il instant.getEpochSecond * 1000 + instant.getNano / 1000000est donc raisonnable de ne pas avoir à faire pour pouvoir communiquer avec les anciennes API (javascript, javascript, javascript, etc.).
Nilskp
10
non, dans ce cas, vous pouvez simplement utiliser instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/…
JodaStephen
20

Avant de faire partie d’openJDK, Threeten était sur github et auparavant sur sourceforge. À l’époque, Stephen Colebourne, responsable des spécifications pour jsr-310, a fait une enquête que vous pouvez toujours trouver sur le site sourceforge .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

seuls 6,23% ont choisi la réponse 4 et parmi eux environ 15% ont demandé un getMillis(), c'est-à-dire moins de 1% du total des voix.

C’est probablement pour cette raison qu’il n’y avait pas d’origine getMilliset que je ne trouvais rien de ce qui se rapportait à la liste de diffusion openjdk, la question n’a donc apparemment pas été abordée par la suite.

Assylias
la source
3
Je pense que donner aux gens plusieurs choix les rend plus susceptibles de choisir l'un de ces choix, même si leur choix idéal est placé sous "autre". Je pourrais toutefois avoir tord.
Allon Guralnek
2
@AllonGuralnek Oui tout à fait. Toutefois, le composant en millisecondes était important dans l'API Date car tout était basé sur un nombre de millisecondes depuis l'époque. Dans la nouvelle API, l'OMI est moins pertinente. Dans la plupart des cas d'utilisation, vous avez besoin d'une seconde précision ou de la meilleure précision disponible (nanos). J'ai peut-être tort.
Assylias
1
Cela semble poser des questions sur la dénomination des méthodes, pas sur les méthodes qui devraient exister.
svick
1
Excusez-moi, je n’étais pas clair: je parlais de la question de l’enquête, à savoir qu’elle ne cherche pas à être directement liée à la question
svick
15

Les classes représentant des heures UTC non ambiguës (Instant, OffsetDateTime, ZoneDateTime) ont deux méthodes d'assistance pour accéder au décalage absolu à partir de l'époque Java, c'est-à-dire ce que vous appelez 'millisecond time' dans java.util.Date, que vous pouvez utiliser. atteindre en millisecondes

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Certaines des raisons pour lesquelles ceci a été choisi à la place de long getEpochMillis()ont été discutées sur la liste de diffusion jsr 310 , dont certaines que j'ai extraites pour des raisons de commodité:

il semble raisonnable de supposer que la précision en millisecondes ne sera pas suffisante. Cependant, toute précision supérieure à la précision nanoseconde semble excessive

...

Pour implémenter ceci, mon option préférée serait une seconde longue de 64 bits (signée) + 32 bits en nanosecondes (non signé).

...

Je préfère que la scission se situe au deuxième niveau car il s’agit de l’unité de temps officielle du SI en sciences et de la norme la plus universellement acceptée.

La division au niveau des jours est problématique pour les instants car elle ne gère pas les secondes intercalaires. La division au niveau des millisecondes, tout en s'intégrant légèrement mieux avec le reste de Java, semble plutôt étrange. De plus, il perd dans la plage prise en charge.

La division à la seconde, comme proposé, donne une plage d’instants de nanosecondes sur 290 milliards d’années. Bien que personne ne devrait jamais utiliser cette précision sur cette plage temporelle, je dirais qu'il est plus facile de la prendre en charge que de la bloquer. Le découpage au niveau des jours est problématique pour les instants car il ne gère pas les secondes intercalaires.

J'ai le sentiment qu'une autre raison était de rendre intentionnellement difficile la conversion de java.util.Date en classes JSR310, en espérant que les développeurs essaient de comprendre les différences entre les différentes options et de ne pas utiliser (aveuglément) les nouvelles classes à l'aveuglette.

Pourquoi la LocalDateTimeclasse ne dispose-t-elle pas de ces méthodes? Elles ne peuvent probablement pas exister là-bas car elles LocalDateTimene sont pas liées à la chronologie UTC tant que vous n'avez pas décidé de la zone dans laquelle vous vous situez ou de votre décalage UTC. OffsetDateTimeou ZonedDateTime(qui ont tous deux les méthodes nécessaires).

Alternativement, vous pouvez définir votre propre LOCAL_EPOCHconstante à 1970-01-01T00:00:00puis faire un MILLIS.between(LOCAL_EPOCH, localTime)pour obtenir une sorte de durée en millisecondes. Toutefois, cette valeur ne sera compatible avec aucune valeur renvoyée par System.currentTimeMilliseconds()ou java.util.Date.getTime(), à moins bien sûr que vous définissiez votre heure locale comme étant l'heure UTC; mais dans ce cas, vous pouvez également utiliser Instant directement ou OffsetDateTime avec ZoneOffset.UTC.

mkadunc
la source
4
" ils ne peuvent pas exister là-bas car LocalDateTime n'est pas lié à la timeline UTC " => un LocalDateTime pourrait certainement avoir une getMillisméthode qui renverrait fondamentalement getNanos()/1e6- le fait que ce ne soit pas un instant dans le temps ne l'empêche pas d'avoir une milliseconde composant.
Assylias
2
" J'ai l'impression qu'une autre raison était de rendre intentionnellement difficile la conversion de java.util.Date aux classes JSR310 " Probablement vrai, mais malheureusement, "millis depuis l'époque" est devenu une représentation quasi universelle du temps, donc pour tout ce qui nécessite pour communiquer avec des API Java plus anciennes, Javascript, toute autre chose, cette omission est un véritable casse-tête.
Nilskp
Votre extrait de code en haut est incorrect - vous devez multiplier le getEpochSecond par 1000.
Tin Man
@nilskp Ce sont deux choses différentes. La question demande à propos de getMillis()comme dans getMillis-of-second; vous parlez de "millis depuis l'époque". Le premier est absent comme expliqué dans la réponse acceptée. Ce dernier est déjà disponible en tant que Instant.toEpochMillis(). Donc, pour un LocalDateTime, vous ldt.toInstant(offset).toEpochMillis()
iriez