JavaRush /Java Blog /Random-TL /Ang isang intuitive, matatag na library para sa pagtatrab...
theGrass
Antas
Саратов

Ang isang intuitive, matatag na library para sa pagtatrabaho sa mga oras at petsa ay sa wakas ay magagamit sa Java (Bahagi 1).

Nai-publish sa grupo
    Sa wakas, ang Java ay may intuitive, maaasahang paraan upang gumana sa mga petsa at oras. Ang mga prinsipyo ng petsa at oras ay mahalaga sa maraming aplikasyon. Iba't ibang bagay tulad ng mga petsa ng kapanganakan, petsa ng pagrenta, oras ng kaganapan, at oras ng pagbubukas ng tindahan ay lahat ay nakabatay sa mga petsa at oras, ngunit hindi nagbigay ang Java SE ng maginhawang paraan upang makipagtulungan sa kanila. Simula sa Java SE 8 , nagkaroon ng set ng java.time packages - na nagbibigay ng mahusay na istrukturang API para sa pagtatrabaho sa mga petsa at oras.
Background
    Noong unang lumabas ang Java , sa bersyon 1.0 , ang tanging klase para sa pagtatrabaho sa mga petsa at oras ay java.util.Date . Ang unang bagay na napansin ng mga developer ay hindi ito kumakatawan sa isang "petsa". Sa katunayan, ito ay kumakatawan sa isang sandali sa oras, tumpak sa millisecond, na sinusukat mula sa petsa ng Enero 1, 1970. Gayunpaman, batay sa katotohanan na ang Date ’s toString() method ay nagpapakita ng petsa at oras sa time zone na tinukoy sa mga setting ng java ng makina , nagkamali ang ilang developer na napagpasyahan na ang Date ay maaaring gumana sa mga time zone. Ang pag-aayos sa klase na ito ay naging napakahirap (o sobrang tamad) na sa bersyon 1.1 kailangan naming magdagdag ng bagong klase - java.util.Calendar . Sa kasamaang palad, ang klase ng Calendar ay naging hindi mas mahusay kaysa sa Petsa . Narito ang isang maliit na listahan ng mga kasalukuyang problema sa pagpapatupad nito:
  • Nababago. Ang mga klase tulad ng petsa at oras ay dapat na hindi nababago.
  • Mga offset. Ang mga taon sa Petsa ay nagsisimula sa 1900, ang mga buwan sa parehong klase ay nagsisimula sa zero.
  • Mga pangalan. Ang petsa ay hindi talaga isang "petsa", at ang Kalendaryo ay hindi isang kalendaryo.
  • Pag-format. Gumagana lang ang pag-format sa Petsa, hindi sa Kalendaryo, at hindi ligtas sa thread.
    Noong 2001, nilikha ang proyekto ng Joda-Time . Ang kanyang layunin ay simple - upang lumikha ng isang mataas na kalidad na library para sa pagtatrabaho sa mga petsa at oras sa Java . Ito ay tumagal ng ilang oras, ngunit ang bersyon 1.0 ay kalaunan ay inilabas at mabilis na naging napakapopular at malawakang ginagamit. Sa paglipas ng panahon, lalong humiling ang mga developer na magbigay ng library na may katulad na kaginhawahan bilang bahagi ng JDK . Sa paglahok ni Michael Nascimento Santos mula sa Brazil, inilunsad ang proyektong JSR-310 , na siyang opisyal na proseso para sa paglikha at pagsasama ng bagong API para sa pagtatrabaho sa mga petsa at oras sa JDK .
Pagsusuri
Ang bagong java.time API ay naglalaman ng 5 pakete:
  • java.time - ang batayang pakete na naglalaman ng mga bagay upang mag-imbak ng mga halaga
  • java.time.chrono - nagbibigay ng access sa iba't ibang mga kalendaryo
  • java.time.format - pag-format at pagkilala ng petsa at oras
  • java.time.temporal - mababang antas ng mga aklatan at advanced na pagpapagana
  • java.time.zone - mga klase para sa pagtatrabaho sa mga time zone
    Karamihan sa mga developer ay gagamit ng base package at pag-format, at marahil java.time.temporal . Kaya, kahit na 68 na mga bagong uri ang naidagdag, ang mga developer ay gagamit lamang ng halos isang katlo ng mga ito.
Petsa
    Ang klase ng LocalDate ay isa sa pinakamahalaga sa bagong API . Naglalaman ito ng hindi nababagong halaga na kumakatawan sa isang petsa. Hindi mo maaaring itakda ang oras o time zone. Ang pangalang "lokal" ay maaaring pamilyar sa iyo mula sa Joda-Time , at orihinal na nagmula sa ISO-8601 standard . Nangangahulugan ito ng tiyak na kawalan ng time zone. Sa pangkalahatan, ang LocalDate ay isang paglalarawan ng isang petsa, gaya ng "ika-5 ng Abril, 2014". Ang aktwal na oras ng petsang ito ay mag-iiba depende sa iyong time zone. Halimbawa, sa Australia ang petsang ito ay magiging 10 oras na mas maaga kaysa sa London, at 18 oras na mas maaga kaysa sa San Francisco. Ang klase ng LocalDate ay mayroong lahat ng karaniwang kinakailangang pamamaraan: LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     Sa aming halimbawa, nakikita namin ang isang petsa na ginawa gamit ang isang factory method (lahat ng mga constructor ay pribado). Susunod na hinihiling namin ang bagay para sa ilang data. Pakitandaan na ang mga enumerasyon ng Buwan at DayOfWeek ay idinisenyo upang gawing mas nababasa at maaasahan ang code. Sa sumusunod na halimbawa ay makikita natin kung paano baguhin ang petsa. Dahil ang klase ay hindi nababago, ang resulta ay magiging mga bagong bagay, ngunit ang orihinal ay mananatiling tulad ng dati. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     Ang mga ito ay medyo simpleng mga pagbabago, ngunit madalas na kailangan mong gumawa ng mas kumplikadong mga pagbabago sa petsa. Mayroong espesyal na mekanismo para dito sa java.time API - TemporalAdjuster . Ang layunin nito ay magbigay ng built-in na tool na nagbibigay-daan sa iyong manipulahin ang mga petsa, halimbawa, pagkuha ng isang bagay na naaayon sa huling araw ng buwan. Ang ilan sa mga ito ay kasama sa API , ngunit maaari mong idagdag ang iyong sarili. Napakadali ng paggamit ng mga modifier, ngunit nangangailangan ito ng mga static na pag-import: import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     Ang paggamit ng mga modifier ay lubos na nagpapasimple sa iyong code. Walang gustong makakita ng maraming manu-manong pagmamanipula ng petsa. Kung ang ilang uri ng pagmamanipula ng petsa ay nangyari nang ilang beses sa iyong proyekto, isulat ang iyong sariling modifier at magagamit ito ng iyong koponan bilang isang nakasulat at nasubok na bahagi.
Oras at petsa bilang mga halaga
    Sulit na gumugol ng kaunting oras sa pag-unawa kung ano ang nagpapahalaga sa LocalDate . Ang mga halaga ay mga simpleng uri ng data na ganap na mapapalitan; kapag sila ay pantay, ang pagkakakilanlan ng mga bagay ay nagiging walang kabuluhan. Ang isang klasikong halimbawa ng isang klase ng halaga ay String . Inihahambing namin ang mga string gamit ang equals() , at wala kaming pakialam kung magkapareho ang mga bagay kapag inihambing sa == operator . Karamihan sa mga klase para sa pagtatrabaho sa mga petsa at oras ay mga halaga din. Kaya, ang paghahambing sa kanila gamit ang == operator ay isang masamang ideya, tulad ng nakasaad sa dokumentasyon. Para sa mga interesadong matuto nang higit pa, tingnan ang aking kamakailang kahulugan ng VALJOs , na nagbabalangkas ng mahigpit na hanay ng mga panuntunan na dapat sundin ng mga bagay na pinahahalagahan sa Java , kabilang ang immutability, factory method, at tamang kahulugan ng equals() , hashCode , toString() , at ihambing Kay .() .
Mga alternatibong kalendaryo
    Ang klase ng LocalDate , tulad ng lahat ng pangunahing klase sa java.time , ay nakatali sa isang kalendaryo - tulad ng inilarawan sa pamantayang ISO-8601 . Inilalarawan ng Standard 8601 ang pandaigdigang pamantayang kalendaryo, na kilala rin bilang kalendaryong Gregorian. Kasama sa karaniwang taon ang 365 araw, isang leap year - 366. Ang bawat ikaapat na taon ay isang leap year maliban kung ito ay nahahati sa 100 o nahahati ng 400. Ang taon bago ang unang taon ng isang bagong panahon ay itinuturing na zero para sa kadalian ng pagkalkula. Ang unang kahihinatnan ng pagiging default na sistema ay ang mga resulta ay hindi palaging tumutugma sa mga kinakalkula gamit ang GregorianCalendar . Ang GregorianCalendar class ay may built-in na switch sa Julian system para sa lahat ng petsa bago ang Oktubre 15, 1582. Sa sistemang Julian, bawat ikaapat na taon ay isang taon ng paglukso, nang walang pagbubukod. Ang tanong ay, dahil ang paglipat mula sa isang sistema patungo sa isa pa ay isang makasaysayang katotohanan, bakit hindi ito modelo ng java.time ? Oo, dahil lumipat ang iba't ibang bansa sa sistemang Gregorian sa iba't ibang panahon, at kung isasaalang-alang lamang ang petsa ng paglipat ng Vatican ay makakakuha tayo ng maling data para sa karamihan ng ibang mga bansa. Halimbawa, ang Imperyo ng Britanya, kabilang ang mga kolonya sa Hilagang Amerika, ay lumipat sa kalendaryong Gregorian noong Setyembre 14, 1752, halos 200 taon na ang lumipas. Hindi binago ng Russia ang kalendaryo nito hanggang Pebrero 14, 1918, at ang paglipat ng Sweden sa pangkalahatan ay isang madilim na bagay. Bilang resulta, ang aktwal na kahulugan ng mga petsa bago ang 1918 ay lubhang nag-iiba depende sa mga pangyayari. Ang mga may-akda ng LocalDate code ay gumawa ng isang ganap na makatwirang desisyon na huwag gawing modelo ang paglipat mula sa Julian na kalendaryo sa Gregorian na kalendaryo sa lahat, upang maiwasan ang mga pagkakaiba. Ang pangalawang kahihinatnan ng paggamit ng ISO-8601 bilang default na kalendaryo sa lahat ng mga pangunahing klase ay ang isang karagdagang hanay ng mga klase ay kinakailangan upang pangasiwaan ang natitirang mga kalendaryo. Ang interface ng Chronology ay ang batayan para sa pagtatrabaho sa mga alternatibong kalendaryo, na nagbibigay-daan sa iyong mahanap ang gustong kalendaryo ayon sa pangalan ng lokal. Ang Java 8 ay may kasamang 4 na karagdagang kalendaryo - Thai Buddhist, Mingguo (Taiwanese), Japanese at Islamic. Maaaring may kasamang mga programa ang ibang mga kalendaryo. Ang bawat kalendaryo ay may espesyal na klase ng petsa gaya ng ThaiBuddhistDate , MinguoDate , JapaneseDate at HijrahDate . Makatuwirang gamitin ang mga ito sa napakataas na naisalokal na mga aplikasyon, tulad ng para sa gobyerno ng Japan. Ang isang karagdagang interface, ChronoLocalDate , ay ginagamit bilang isang pangunahing abstraction ng apat na klase sa itaas kasama ng LocalDate, na nagbibigay-daan sa iyong magsulat ng code na hiwalay sa uri ng kalendaryong ginamit. Bagama't umiiral ang abstraction na ito, hindi inirerekomenda ang paggamit nito. Ang pag-unawa kung bakit hindi inirerekomenda ang abstraction na ito ay mahalaga sa pag-unawa kung paano gumagana ang buong java.time API . Ang bottom line ay ang karamihan sa code na nakasulat nang walang reference sa isang partikular na kalendaryo ay lumalabas na hindi gumagana. Halimbawa, hindi ka makatitiyak na mayroong 12 buwan sa isang taon, ngunit ang ilang mga developer ay nagdaragdag ng 12 buwan at iniisip na nagdagdag sila ng isang buong taon. Hindi ka makatitiyak na ang lahat ng buwan ay naglalaman ng humigit-kumulang sa parehong bilang ng mga araw - sa kalendaryong Coptic ay mayroong 12 buwan ng 30 araw, at 1 buwan ng lima o anim na araw. Gayundin, hindi ka makatitiyak na ang bilang ng susunod na taon ay magiging 1 higit pa kaysa sa kasalukuyan, dahil sa kalendaryo ng Hapon, ang mga taon ay binibilang mula sa proklamasyon ng susunod na emperador (sa kasong ito, kahit na 2 araw ng parehong buwan maaaring kabilang sa iba't ibang taon). Ang tanging paraan upang magsulat ng mataas na kalidad at gumaganang code na gumagana sa ilang mga kalendaryo nang sabay-sabay ay ang core ng iyong code, na gumaganap ng lahat ng mga operasyon sa mga petsa at oras, ay dapat na nakasulat gamit ang isang karaniwang kalendaryo, at kapag nagpapasok/naglalabas lamang ng mga petsa dapat itong i-convert sa ibang mga sistema ng kalendaryo. Iyon ay, inirerekumenda na gumamit ng LocalDate para sa imbakan at lahat ng pagmamanipula ng petsa sa iyong aplikasyon. At kapag naglo-localize lamang ng mga petsa ng input at output ay dapat mong gamitin ang ChronoLocalDate , na karaniwang nakukuha mula sa klase ng kalendaryo na nakaimbak sa profile ng user. Totoo, karamihan sa mga application ay hindi nangangailangan ng ganitong seryosong lokalisasyon. Kung kailangan mo ng mas detalyadong paliwanag sa lahat ng inilarawan sa kabanatang ito, maligayang pagdating sa dokumentasyon ng klase ng ChronoLocalDate .      Pagpapatuloy ng artikulo      Orihinal na artikulo
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION