De ce clasele Java 8 java.time nu au o metodă getMillis()? (Inginerie software, Java, Java8)

Tarmo a intrebat.

Java 8 are o bibliotecă complet nouă pentru date și ore în pachetul java.time, care este un lucru foarte binevenit pentru oricine a trebuit să folosească JodaTime înainte sau să se chinuie să creeze propriile metode de ajutor pentru procesarea datelor. Multe clase din acest pachet reprezintă timestamp-uri și au metode ajutătoare precum getHour() pentru a obține orele din timestamp, getMinute() pentru a obține minute din timestamp, getNano() pentru a obține nanos din timestamp etc…

Am observat că nu au o metodă numită getMillis() pentru a obține milis din marca temporală. În schimb, ar trebui să se apeleze metoda get(ChronoField.MILLI_OF_SECOND). Mie mi se pare că este o inconsecvență în bibliotecă. Știe cineva de ce lipsește o astfel de metodă sau, cum Java 8 este încă în dezvoltare, există posibilitatea ca aceasta să fie adăugată mai târziu?

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

Clasele definite aici reprezintă principalele concepte de dată-timp, inclusiv instanți, durate, date, ore, fusuri orare și perioade. Acestea se bazează pe sistemul calendaristic ISO, care este sistemul de facto mondial de facto, care urmează regulile proleptice ale calendarului gregorian. Toate clasele sunt imuabile și sigure pentru fire de execuție.

Fiecare instanță de dată și oră este compusă din câmpuri care sunt puse la dispoziție în mod convenabil de către API-uri. Pentru accesarea la nivel inferior a câmpurilor, consultați java.time.temporal pachet. Fiecare clasă include suport pentru tipărirea și analizarea a tot felul de date și ore. A se vedea java.time.format pentru opțiuni de personalizare…

Exemplu de acest tip de clasă:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

O dată-timp fără un fus orar în sistemul de calendar ISO-8601, cum ar fi 2007-12-03T10:15:30.

LocalDateTime este un obiect imuabil de tip data-timp care reprezintă o dată-timp, deseori vizualizată ca an-lună-zi-ora-minut-secundă. De asemenea, pot fi accesate și alte câmpuri de dată și oră, cum ar fi ziua anului, ziua săptămânii și săptămâna anului. Timpul este reprezentat cu o precizie de o nanosecundă. De exemplu, valoarea „2nd October 2007 at 13:45.30.123456789” poate fi stocată într-un fișier LocalDateTime

Comentarii

  • Se pare că au vrut să folosească polimorfismul pentru a rezolva o grămadă de metode, toate numite get(), , în loc să le dea nume individuale și unice. Dacă vă deranjează, scrieți o clasă care moștenește clasa originală și puneți propriile dvs. getMillis() în noua clasă. –  > Por Robert Harvey.
  • @RobertHarvey Majoritatea claselor din pachetul java.time sunt imuabile și nu pot fi extinse. –  > Por assylias.
  • @RobertHarvey Întrebarea pentru mine nu este cum pot rezolva acest lucru. Mi s-a părut doar o inconsecvență ciudată și mă întrebam dacă există o explicație interesantă pentru acest lucru. –  > Por Tarmo.
  • Am ideea că unele arhitecturi/OS nu suportă în mod fiabil milisecundele. Cu alte cuvinte, timpul sistemului nu poate fi recuperat la milisecundă, ci doar la centi- sau decisecundă. –  > Por Marco.
  • Vezi stackoverflow.com/a/2394545792/40064 despre o modalitate de a face acest lucru prin intermediul aplicației Instant class –  > Por Wim Deblauwe.
3 răspunsuri
JodaStephen

JSR-310 se bazează pe nanosecunde, nu pe milisecunde. Ca atare, setul minim de metode sensibile se bazează pe oră, minute, secundă și nanosecundă. Decizia de a avea o bază de nanosecunde a fost una dintre deciziile inițiale ale proiectului și una pe care o consider cu tărie corectă.

Adăugarea unei metode pentru milisecunde s-ar suprapune peste cea pentru nanosecunde într-un mod neevident. Utilizatorii ar trebui să se gândească dacă domeniul nano este de exemplu nano de secundă sau nano de mililitru. Adăugarea unei metode suplimentare derutante nu este de dorit, astfel încât metoda a fost omisă. După cum s-a subliniat, alternativa get(MILLI_OF_SECOND) este disponibilă.

Pentru a fi sincer, m-aș opune adăugării metodei getMillis() metoda în viitor.

Comentarii

  • Am primit câteva răspunsuri foarte bune la această întrebare, dar răspunsul dvs. este preferatul meu, deoarece este scurt, dar totuși prezintă un punct de vedere foarte bun și mă convinge cu adevărat de necesitatea acestei abordări. Vă mulțumesc. –  > Por Tarmo.
  • @s3ib dacă verificați profilul celui care a răspuns, veți observa, de asemenea, că este un responsabil cu specificațiile pentru același API despre care întrebați. Acest lucru face ca un răspuns să fie cât se poate de autorizat, nu-i așa 🙂 –  > Por gnat.
  • Deci, având în vedere că trebuie să faceți instant.getEpochSecond * 1000 + instant.getNano / 1000000 este un boilerplate rezonabil pentru a putea comunica cu API-urile Java (în acest moment, toate), Javascript, etc.? –  > Por nilskp.
  • nu, în acest caz, puteți utiliza pur și simplu instant.toEpochMilli() download.java.net/jdk8/docs/api/java/java/time/… –  > Por JodaStephen.
assylias

Înainte de a face parte din openJDK, threeten a fost pe github și înainte de asta a fost pe sourceforge. Pe atunci, Stephen Colebourne, care este lider de specificații pentru jsr-310, a făcut un sondaj pe care îl puteți găsi și acum. pe site-ul 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

Doar 6,23% au ales răspunsul nr. 4, iar dintre aceștia aproximativ 15% au cerut un getMillis(), adică mai puțin de 1% din totalul voturilor.

Probabil că acesta este motivul pentru care nu a existat getMillis în primul rând și nu am putut găsi nimic în legătură cu aceasta pe lista de discuții openjdk, astfel încât se pare că problema nu a fost discutată ulterior.

Comentarii

  • Cred că, dacă le oferim oamenilor mai multe opțiuni, este mai probabil ca aceștia să aleagă una dintre ele, chiar dacă opțiunea lor ideală se află la rubrica „altele”. S-ar putea să mă înșel, totuși. –  > Por Allon Guralnek.
  • @AllonGuralnek Da, cu siguranță – cu toate acestea, componenta de milisecunde a fost importantă în API-ul Date, deoarece totul se baza pe un număr de milisecunde de la epocă. În noua API, este mai puțin relevantă, potrivit IMO. În majoritatea cazurilor de utilizare, aveți nevoie fie de o precizie de o secundă, fie de cea mai bună precizie disponibilă (nanos). S-ar putea să mă înșel. –  > Por assylias.
  • Se pare că această întrebare se referă la denumirea metodelor, nu despre ce metode ar trebui să existe. –  > Por svick.
  • Corect, îmi pare rău, nu am fost clar: mă refeream la întrebarea din sondaj, care nu caută o legătură directă cu această întrebare. –  > Por svick.
mkadunc

Clasele care reprezintă timpi UTC neechivoci (acestea sunt Instant, OffsetDateTime, ZonedDateTime) au două metode de ajutor pentru a accesa decalajul absolut față de epoca Java, adică ceea ce se numește „milisecond time” în java.util.Date, pe care le-ai putea folosi pentru a ajunge la milisecunde

long getEpochSecond()
int getNano()

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

Câteva motive pentru care a fost ales acest lucru în loc de long getEpochMillis() au fost discutate pe lista de discuții jsr 310, , dintre care am extras câteva pentru comoditate:

pare rezonabil să presupunem că precizia în milisecunde nu va fi suficientă. Cu toate acestea, orice precizie mai mare de o nanosecundă pare excesivă

Pentru a implementa acest lucru, opțiunea mea preferată ar fi 64 bit long seconds (signed) + 32 bit int nanoseconds (unsigned).

Prefer ca împărțirea să se facă la al doilea nivel, deoarece aceasta este unitatea de timp SI oficială în știință și este cel mai universal acceptat standard.

Împărțirea la nivelul zilelor este problematică pentru instanți, deoarece nu gestionează secundele bisecunde. Împărțirea la nivel de milisecunde, deși se integrează puțin mai bine cu restul Java, pare într-adevăr destul de ciudată. În plus, se pierde în intervalul acceptat.

Împărțirea la nivel de secundă, așa cum se propune, oferă o gamă de instanți de nanosecunde pe o perioadă de 290 de miliarde de ani. Deși nimeni nu ar trebui să folosească vreodată o asemenea precizie în acest interval de timp, aș sugera că este mai ușor să o susținem decât să o blocăm. împărțirea la nivel de zile este problematică pentru instanți, deoarece nu gestionează secundele bisecunde.

Am sentimentul că un alt motiv a fost acela de a îngreuna în mod intenționat conversia de la clasele java.util.Date la clasele JSR310, în speranța că dezvoltatorii vor încerca să înțeleagă diferențele dintre diferitele opțiuni și nu vor folosi orbește (greșit) noile clase.

În ceea ce privește motivul pentru care LocalDateTime clasa nu are aceste metode – nu este posibil ca ele să existe acolo deoarece LocalDateTime nu este legată de linia de timp UTC până când nu decideți în ce zonă vă aflați sau care este decalajul UTC, moment în care aveți o clasă de tip OffsetDateTime sau ZonedDateTime (ambele având metodele necesare).

Alternativ, ați putea să vă definiți propriul LOCAL_EPOCH constantă pentru 1970-01-01T00:00:00 și apoi să efectuați un MILLIS.between(LOCAL_EPOCH, localTime) pentru a obține un fel de durată în milisecunde. Această valoare, însă, nu va fi compatibilă cu nicio valoare returnată de către System.currentTimeMilliseconds() sau java.util.Date.getTime(), , cu excepția cazului în care, desigur, definiți ora locală ca fiind ora UTC; dar în acest caz, ați putea la fel de bine să folosiți direct Instant sau OffsetDateTime cu ZoneOffset.UTC.

Comentarii

  • nu pot exista acolo, deoarece LocalDateTime nu este legat de linia de timp UTC.” => un LocalDateTime ar putea avea cu siguranță un getMillis care ar returna practic getNanos()/1e6 – faptul că nu este un moment în timp nu îl împiedică să aibă o componentă de milisecunde. –  > Por assylias.
  • Am impresia că un alt motiv a fost acela de a îngreuna intenționat conversia din clasele java.util.Date în clase JSR310” Probabil că este adevărat, dar, din păcate, „milis de la epocă” a devenit o reprezentare aproape universală a timpului, așa că pentru orice lucru care trebuie să comunice cu API-uri Java mai vechi, Javascript, orice altceva, această omisiune este o adevărată bătaie de cap. –  > Por nilskp.
  • Fragmentul tău de cod din partea de sus este incorect – trebuie să înmulțești getEpochSecond cu 1000. –  > Por Tin Wizard.
  • @nilskp Sunt două lucruri diferite. Întrebarea se referă la getMillis() ca în getMillis-of-second; tu vorbești despre „milis de la epocă”. Primul este absent, așa cum se explică în răspunsul acceptat. Acesta din urmă este deja disponibil ca Instant.toEpochMillis(). Deci, pentru un LocalDateTime, , ar trebui să faceți: ldt.toInstant(offset).toEpochMillis() –  > Por SusanW.

Tags:,