Ohjelmistokehittäjänä et voi paeta päivämäärän manipulointia. Lähes jokaisessa kehittäjän rakentamassa sovelluksessa on jokin komponentti, josta päivämäärä / aika on hankittava käyttäjältä, tallennettava tietokantaan ja näytettävä käyttäjälle.
Kysy ohjelmoijalta kokemusten käsittelyn päivämäärät ja aikavyöhykkeet, ja he todennäköisesti jakavat joitain sotatarinoita. Päivämäärä- ja aikakenttien käsittely ei todellakaan ole rakettitiedettä, mutta se voi usein olla tylsää ja alttiita virheille.
Aiheesta on satoja artikkeleita, mutta suurin osa niistä on joko liian akateemisia, keskittyen hienovaraisiin yksityiskohtiin, tai ovat liian hajanaisia, ja tarjoavat lyhyitä koodinpätkiä ilman paljon selityksiä niiden mukana. Tämän DateTime-manipuloinnin perusteellisen oppaan pitäisi auttaa sinua ymmärtämään ajan ja päivämäärän kannalta merkityksellisiä ohjelmointikonsepteja ja parhaita käytäntöjä tarvitsematta selata merta tietoa tästä aiheesta.
Tässä artikkelissa autan sinua ajattelemaan selkeästi päivämäärä- ja aikakenttiä ja ehdottamaan joitain parhaita käytäntöjä, joiden avulla voit välttää päivämäärän ja ajan helvetin. Tässä tutkitaan joitain keskeisiä käsitteitä, jotka ovat välttämättömiä päivämäärä- ja aika-arvojen oikein manipuloimiseksi, muotoja, jotka ovat käteviä DateTime-arvojen tallentamiseen ja niiden siirtämiseen API: n kautta, ja paljon muuta.
Ensinnäkin, oikea vastaus tuotantokoodiin on melkein aina käyttää oikeaa kirjastoa oman omistamisen sijaan. Tässä artikkelissa käsitellyt mahdolliset vaikeudet DateTime-laskennassa ovat vain jäävuoren huippu, mutta niistä on silti hyödyllistä tietää kirjaston kanssa tai ilman.
Päiväkirjastot helpottavat elämääsi monin tavoin. Ne yksinkertaistavat huomattavasti päivämäärän jäsentämistä, päivämäärän aritmeettisia ja loogisia toimintoja sekä päivämäärän muotoilua. Löydät luotettavan päivämääräkirjaston sekä etu- että takapäähän tekemään suurimman osan raskaasta nostosta puolestasi.
Käytämme kuitenkin usein päivämääräkirjastoja ajattelematta, miten päiväys / aika todella toimii. Päivämäärä / aika on monimutkainen käsite. Virheitä, jotka johtuvat sen virheellisestä ymmärryksestä, voi olla äärimmäisen vaikea ymmärtää ja korjata jopa päiväkirjastojen avulla. Ohjelmoijana sinun on ymmärrettävä perusasiat ja pystyttävä ymmärtämään ongelmat, jotka päiväkirjastot ratkaisevat hyödyntääkseen niitä parhaalla mahdollisella tavalla.
Päivämäärä / aika-kirjastot voivat myös viedä sinut vain niin pitkälle. Kaikki päivämääräkirjastot toimivat antamalla sinulle pääsyn käteviin datarakenteisiin, jotka edustavat DateTime-aikaa. Jos lähetät ja vastaanotat tietoja REST-sovellusliittymän kautta, sinun on lopulta muunnettava päivämäärä merkkijonoksi ja päinvastoin, koska JSON: lla ei ole natiivia tietorakennetta, joka edustaisi DateTime-aikaa. Tässä hahmottelemani käsitteet auttavat sinua välttämään joitain yleisiä ongelmia, joita saattaa esiintyä, kun teet näitä päivämäärästä merkkijonoon ja merkkijonosta päivämäärään -muutoksia.
Huomautus: Vaikka olen käyttänyt JavaScript Tässä artikkelissa käsiteltävänä ohjelmointikielenä nämä ovat yleisiä käsitteitä, joita sovelletaan suurelta osin käytännöllisesti katsoen kaikkiin ohjelmointikieliin ja niiden päivämääräkirjastoihin. Joten vaikka et ole koskaan kirjoittanut JavaScriptiä aiemmin, jatka lukemista, koska tuskin oletan, että artikkelissa olisi ennalta tietoa JavaScriptiin.
DateTime on hyvin tarkka ajankohta. Ajatelkaamme tätä. Kun kirjoitan tätä artikkelia, kannettavan tietokoneen kello näyttää 21. heinäkuuta 13.29. Tätä kutsumme 'paikalliseksi ajaksi', aikaa, jonka näen ympärilläni olevissa seinäkelloissa ja rannekellossani.
Anna tai vie muutama minuutti, jos pyydän ystävääni tapaamaan minut läheisessä kahvilassa klo 15.00, voin odottaa hänen näkevän siellä suunnilleen tuolloin. Vastaavasti ei olisi hämmennystä, jos sanoisin sen sijaan esimerkiksi 'tapaamme puolitoista tuntia'. Puhumme säännöllisesti ajasta tällä tavalla ihmisten kanssa, jotka asuvat samassa kaupungissa tai aikavyöhykkeellä.
Ajattele erilaista skenaariota: Haluan kertoa Uppsalassa Ruotsissa asuvalle ystävällesi, että haluan puhua hänen kanssaan kello 17.00. Lähetän hänelle viestin: 'Hei Anton, puhutaan kello 17.00.' Saan heti vastauksen 'Aikani vai aikani?'
Anton kertoo minulle, että hän asuu Keski-Euroopan aikavyöhykkeellä, joka on UTC + 01: 00. Asun UTC + 05: 45. Tämä tarkoittaa, että kun asun, on kello 17.00, kello on 17.00–05.45 = 11.15 UTC, mikä tarkoittaa Uppsalassa kello 11.15 UTC + 13.00 = 12.15. meistä.
Ota huomioon myös aikavyöhykkeen (Keski-Euroopan aika) ja aikavyöhykesiirron (UTC + 05: 45) välinen ero. Maat voivat päättää muuttaa aikavyöhyke-eroja kesäaikaan myös poliittisista syistä. Lähes joka vuosi sääntöjä muutetaan ainakin yhdessä maassa, eli kaikki koodit, joissa nämä säännöt paistetaan, on pidettävä ajan tasalla - kannattaa miettiä, mistä koodikantaasi riippuu tältä sovelluksesi jokaiselle tasolle.
Tämä on toinen hyvä syy, jonka vuoksi suosittelemme, että vain käyttöliittymä käsittelee aikavyöhykkeitä useimmissa tapauksissa. Kun ei, mitä tapahtuu, kun tietokantakoneesi käyttämät säännöt eivät vastaa etu- tai takapään sääntöjä?
Tämä kahden ajan eri version hallinnan ongelma suhteessa käyttäjään ja yleisesti hyväksyttyyn standardiin on vaikea, varsinkin ohjelmointimaailmassa, jossa tarkkuus on avainasemassa ja jopa sekunnissa voi olla valtava ero. Ensimmäinen askel kohti näiden ongelmien ratkaisemista on tallentaa DateTime UTC: hen.
Ajan vakiointi on hienoa, koska minun tarvitsee vain tallentaa UTC-aika ja niin kauan kuin tiedän käyttäjän aikavyöhykkeen, voin aina muuntaa heidän aikaansa. Vastaavasti, jos tiedän käyttäjän paikallisen ajan ja tiedän hänen aikavyöhykkeensä, voin muuntaa sen UTC: ksi.
Mutta päivämäärät ja kellonajat voidaan määrittää monissa eri muodoissa. Päivämääräksi voit kirjoittaa '30. heinäkuuta', '30. heinäkuuta' tai '7/30' (tai 30/7, asuinpaikkasi mukaan). Voit tällä hetkellä kirjoittaa '21:30' tai '2130'.
Tutkijat ympäri maailmaa kokoontuivat käsittelemään tätä ongelmaa ja päättivät muodon kuvaamaan aikaa, jota ohjelmoijat todella pitävät, koska se on lyhyt ja tarkka. Haluamme kutsua sitä 'ISO-päivämäärämuodoksi', joka on yksinkertaistettu versio laajennetusta ISO-8601-muodosta ja näyttää tältä:
Klo 00:00 tai UTC käytämme sen sijaan 'Z', mikä tarkoittaa Zulun aikaa, UTC: n toista nimeä.
Ennen kuin aloitamme parhaiden käytäntöjen kanssa, opimme päivämäärän manipuloinnista JavaScriptin avulla saadaksemme käsityksen syntaksista ja yleisistä käsitteistä. Vaikka käytämme JavaScriptiä, voit mukauttaa nämä tiedot haluamaasi ohjelmointikieleen helposti.
Käytämme päivämääräaritmeettista ratkaistaksemme yleisiä päivämäärään liittyviä ongelmia, joita useimmat kehittäjät kohtaavat.
Tavoitteenani on tehdä sinusta mukava luoda päivämääräobjekti merkkijonosta ja purkaa komponentit yhdestä. Päiväkirjasto voi auttaa tässä, mutta on aina parempi ymmärtää, miten se tapahtuu kulissien takana.
Kun päivä ja aika on likaantunut, on helpompaa miettiä kohtaamiamme ongelmia, poimia parhaat käytännöt ja edetä. Jos haluat siirtyä parhaisiin käytäntöihin, tee niin, mutta suosittelen sinua ainakin selaamaan alla olevan päivämääräaritmeettisen osan läpi.
Ohjelmointikielet sisältävät hyödyllisiä rakenteita, jotka helpottavat elämäämme. JavaScript Date
esine on yksi sellainen asia. Se tarjoaa käteviä menetelmiä nykyisen päivämäärän ja kellonajan hankkimiseksi, päivämäärän tallentamiseksi muuttujaan, päivämäärän aritmeettisen suorituksen ja päivämäärän muotoilemiseksi käyttäjän sijainnin mukaan.
Selainratkaisujen erojen ja kesäajan (DST) virheellisen käsittelyn vuoksi päivämääräobjektista riippuen tehtäväkriittisiä sovelluksia ei suositella, ja sinun on todennäköisesti käytettävä DateTime-kirjastoa, kuten Luxon, date-fns tai dayjs . (Käytä mitä tahansa, vältä kerran suosittua Moment.js-tiedostoa, jota kutsutaan usein vain moment
, kuten koodissa näkyy, koska se on nyt vanhentunut.)
Mutta opetustarkoituksiin käytämme Date () -objektin tarjoamia menetelmiä oppiakseen, kuinka JavaScript käsittelee DateTime-aikaa.
const currentDate = new Date();
Jos et välitä mitään Date-rakentajalle, palautettu päivämäärä-objekti sisältää nykyisen päivämäärän ja kellonajan.
Voit sitten muotoilla sen purkamaan vain päiväysosan seuraavasti:
const currentDate = new Date(); const currentDayOfMonth = currentDate.getDate(); const currentMonth = currentDate.getMonth(); // Be careful! January is 0, not 1 const currentYear = currentDate.getFullYear(); const dateString = currentDayOfMonth + '-' + (currentMonth + 1) + '-' + currentYear; // '27-11-2020'
Huomaa: ”Tammikuu on 0” -kuoppa on yleinen, mutta ei yleinen. Ennen kuin aloitat sen käytön, kannattaa tarkistaa minkä tahansa kielen (tai määritysmuodon: esim. Cron on erityisesti 1-pohjainen) dokumentaatio.
Jos haluat sen sijaan hankkia nykyisen aikaleiman, voit luoda uuden Date-objektin ja käyttää getTime () -menetelmää.
const currentDate = new Date(); const timestamp = currentDate.getTime();
Aikaleima on JavaScriptissä 1. tammikuuta 1970 jälkeen kuluneiden millisekuntien lukumäärä.
Jos et aio tukea Merkkijono muunnetaan JavaScript-päivämääräobjektiksi eri tavoin. Date-objektin rakentaja hyväksyy monenlaisia päivämäärämuotoja: Huomaa, että sinun ei tarvitse sisällyttää viikonpäivää, koska JS voi määrittää viikonpäivän mille tahansa päivämäärälle. Voit myös kuluttaa vuoden, kuukauden, päivän, tunnit, minuutit ja sekunnit erillisinä argumentteina: Tietenkin voit aina käyttää ISO-päivämäärämuotoa: Voit kuitenkin törmätä vaikeuksiin, jos et anna aikavyöhykettä nimenomaisesti! Kumpi tahansa näistä antaa sinulle 25. heinäkuuta 2016 00:00:00 paikallista aikaa. Jos käytät ISO-muotoa, vaikka annat vain päivämäärän eikä aikaa ja aikavyöhykettä, se hyväksyy aikavyöhykkeen automaattisesti UTC: ksi. Se tarkoittaa, että: Onneksi nykyaikaisella JavaScriptillä on joitain käteviä kansainvälistystoimintoja, jotka on sisällytetty standardiin Tätä varten tarvitsemme kahta kohdetta: a Jos sen sijaan haluaisimme hollantilaisen (D / M / YYYY) muodon, välitämme vain toisen kulttuurikoodin Tai pidempi muoto amerikkalaisesta muodosta, jossa kuukauden nimi on kirjoitettu: Jos nyt halusimme oikean järjestysmuodon kuukauden päivänä eli '14.' vain '14': n sijaan, tämä valitettavasti tarvitsee hieman kiertotapaa, koska Valitettavasti Jos sinun on tuettava vanhempia selaimia, kuten IE ennen versiota 11, päivämäärän muotoilu JavaScript-ohjelmassa on tiukempi, koska normaalia päivämäärän muotoilutoimintoa, kuten Esimerkiksi PHP: ssä funktio Voit käyttää a erilainen kirjainyhdistelmä edeltää Jos olet varma käyttämästäsi muodosta, on parasta purkaa yksittäiset bitit käyttämällä yllä mainittuja JavaScript-toimintoja ja luoda itse merkkijono. Voimme saada päivämäärän muodossa KK / PP / VVVV muodossa Tämän ratkaisun ongelmana on, että se voi antaa päivämäärille epäjohdonmukaisen pituuden, koska jotkut kuukaudet ja päivät ovat yksinumeroisia ja toiset kaksinumeroisia. Tämä voi olla ongelmallista, jos esimerkiksi näytät päivämäärää taulukon sarakkeessa, koska päivämäärät eivät ole rivissä. Voimme puuttua tähän käyttämällä 'pad' -toimintoa, joka lisää 0: n. Nyt saamme oikean päivämäärän muodossa KK / PP / VVVV muodossa: Jos haluamme sen sijaan PP-KK-VVVV, prosessi on samanlainen: Aloitetaan ante ja yritetään tulostaa päivämäärä 'Kuukauden päivä, vuosi' -muodossa. Tarvitsemme kuukausihakemistojen kartoituksen nimiin: Jotkut ihmiset haluavat näyttää päivämäärän 1. tammikuuta 2013. Ei hätää, tarvitsemme vain aputoiminnon Viikonpäivä on helppo määrittää päivämääräobjektista, joten lisätään se: Suurempi asia on, että kun olet saanut numerot otetuista päivämäärästä, muotoilu liittyy enimmäkseen merkkijonoihin. Kun tiedät kuinka jäsentää päivämäärä ja muotoilla se, päivämäärän vaihtaminen muodosta toiseen on vain kyse näiden kahden yhdistämisestä. Esimerkiksi, jos sinulla on päivämäärä muodossa 21.7.2013 ja haluat muuttaa muotoa 21-07-2013, se voidaan saavuttaa seuraavasti: Edellä käsittelemiemme päivämäärän muotoilumenetelmien pitäisi toimia useimmissa sovelluksissa, mutta jos haluat todella lokalisoida päivämäärän muotoilun, suosittelen, että käytät … Antaa meille jotain Jos kieliasetukseksi vaihdetaan 'fi-US', sen sijaan saadaan '26.7.2016'. Huomaa, kuinka muotoilu muuttui, mutta näyttövaihtoehdot pysyivät ennallaan - erittäin hyödyllinen ominaisuus. Kuten edellisessä osiossa on esitetty, uudempi Jos halusin sen sijaan koko kuukauden “heinäkuu”, teen vain vaihtoehdon kuukausi-parametrin ”pitkä”. JavaScript hoitaa kaiken minulle. En-USA: lle saan nyt 26. heinäkuuta 2016. Huomaa: Jos haluat selaimen käyttävän automaattisesti käyttäjän aluetta, voit antaa ensimmäiseksi parametriksi 'määrittelemätön'. Jos haluat näyttää päivämäärän numeerisen version etkä halua murehtia KK / PP / VVVV vs. PP / KK / VVVV eri alueilla, suosittelen seuraavaa yksinkertaista ratkaisua: Tietokoneellani tämä antaa Tämä antaa Voit käyttää myös joitain muita toimintoja paikallistaaksesi ajan sekä päivämäärän näyttötavan: Tässä on esimerkki 20 päivän lisäämisestä JavaScript-päivämäärään (eli päivämäärän selvittäminen 20 päivää tunnetun päivämäärän jälkeen): Alkuperäinen päivämääräobjekti edustaa nyt päivämäärää 20 päivää 20. heinäkuuta jälkeen ja Voit laskea suhteelliset aikaleimat tarkemmalla erolla kuin kokonaiset päivät, käyttämällä Kuten kaikilla muilla päivämäärään liittyvillä, myös päivämäärien vertailulla on omat juttuja. Ensinnäkin meidän on luotava päivämääräobjekteja. Onneksi, = kaikki toimivat. Joten 19. heinäkuuta 2014 ja 18. heinäkuuta 2014 vertailla on yhtä helppoa kuin: Tasa-arvon tarkistaminen on hankalampaa, koska kaksi samaa päivämäärää edustavaa päivämääräobjektia ovat edelleen kaksi erilaista päivämääräobjektia eivätkä ole yhtä suuret. Päivämäärämerkkijonojen vertaaminen on huono idea, koska esimerkiksi '20. heinäkuuta 2014' ja '20. heinäkuuta 2014' edustavat samaa päivämäärää, mutta niillä on erilaiset merkkijonojen esitykset. Alla oleva katkelma kuvaa ensimmäistä kohtaa: Tämä tuottaa Tämä tapaus voidaan korjata vertaamalla päivämäärien kokonaislukuekvivalentteja (niiden aikaleimat) seuraavasti: Olen nähnyt tämän esimerkin monissa paikoissa, mutta en pidä siitä, koska et luo päivämääräobjektia toisesta päivämääräobjektista yleensä. Joten mielestäni esimerkki on tärkeä vain akateemisesta näkökulmasta. Tämä edellyttää myös, että molemmat Date-objektit viittaavat täsmälleen samaan sekuntiin, kun taas haluat ehkä tietää vain, jos ne viittaavat samaan päivään, tuntiin tai minuuttiin. Katsotaanpa käytännöllisempää esimerkkiä. Yrität verrata, onko käyttäjän kirjoittama syntymäpäivä sama kuin onnekas päivä, jonka saat sovellusliittymältä. Molemmat edustivat samaa päivämäärää, mutta valitettavasti käyttäjäsi ei saa miljoona dollaria. Tässä on ongelma: JavaScript olettaa aina aikavyöhykkeen olevan selaimen antama aikavyöhyke, ellei nimenomaisesti toisin mainita. Minulle tämä tarkoittaa Ainoastaan olemassa olevan päivämääräobjektin aikavyöhykettä ei voi muuttaa, joten tavoitteemme on nyt luoda uusi päivämääräobjekti, mutta käyttämällä UTC: tä paikallisen aikavyöhykkeen sijaan. Ohitamme käyttäjän aikavyöhykkeen ja käytämme UTC: tä luodessamme päivämääräobjektia. Voit tehdä sen kahdella tavalla: Tämä toimii myös, jos et määritä aikaa, koska oletuksena on keskiyö (ts. 00: 00: 00Z): Muista: Jos päivämääränrakentajalle syötetään merkkijono oikeassa ISO-päiväysmuodossa VVVV-KK-PP, se ottaa UTC: n automaattisesti. Tavallinen tapauksesi on löytää ero kahden päivämäärän välillä. Keskustelemme kahdesta käyttötapauksesta: Muunna molemmat päivämäärät UTC-aikaleimaksi, etsi ero millisekunteina ja etsi vastaavat päivät. Huomaa: Meillä on epätyypillinen muoto. Lue API-asiakirja selvittääkseen, tarkoittaako tämä 12. lokakuuta vai 10. joulukuuta. Vaihda vastaavasti ISO-muotoon. Tiedän, että on olemassa suppeampia tapoja kirjoittaa tämä koodi, mutta haluan kirjoittaa sen tällä tavalla logiikan selkeyden takia. Nyt kun olemme tyytyväisiä päivämäärälaskelmiin, pystymme ymmärtämään parhaita käytäntöjä ja syitä niiden noudattamiseen. Jos saat päivämäärän ja kellonajan käyttäjältä, etsit todennäköisesti hänen paikallista DateTime-aikaa. Päivämääräaritmeettisessa osassa näimme, että Hämmennysten poistamiseksi ehdotan aina päivämäärän luomista käyttämällä Hienoa on, että voit käyttää muunnelmia, joiden avulla voit jättää minkä tahansa neljästä viimeisestä parametrista pois, jos ne ovat nollia. eli Jos esimerkiksi käytät päivämäärän ja ajan valitsinta, joka antaa sinulle päivämäärän 2012-10-12 ja kellonajan 12:30, voit purkaa osat ja luoda uuden Date-objektin seuraavasti: Yritä välttää päivämäärän luomista merkkijonosta, ellei se ole ISO-päivämäärämuodossa. Käytä sen sijaan Päivämäärä (vuosi, kuukausi, päivämäärä, tunnit, minuutit, sekunnit, mikrosekunnit) -menetelmää. Jos saat vain päivämäärän, esimerkiksi käyttäjän syntymäpäivän, on parasta muuntaa muoto kelvolliseksi ISO-päivämäärämuodoksi, jotta vältetään kaikki aikavyöhyketiedot, jotka voivat aiheuttaa päivämäärän siirtymisen eteenpäin tai taaksepäin muunnettaessa UTC: ksi. Esimerkiksi: Jos unohdit, jos luot Säilytä DateTime aina UTC: ssä. Lähetä aina ISO-päivämäärämerkkijono tai aikaleima loppupäähän. Tietokoneohjelmoijien sukupolvet ovat ymmärtäneet tämän yksinkertaisen totuuden katkerien kokemusten jälkeen yrittäessään näyttää oikean paikallisen ajan käyttäjälle. Paikallisen ajan tallentaminen takapäähän on huono idea, on parempi antaa selaimen hoitaa muunnos paikalliseksi ajaksi käyttöliittymässä. Lisäksi pitäisi olla ilmeistä, että sinun ei pitäisi koskaan lähettää DateTime-merkkijonoa, kuten “20. heinäkuuta 1989 12:10 PM”, loppupäähän. Vaikka lähetät myös aikavyöhykkeen, lisäät muiden ohjelmoijien ponnisteluja ymmärtää aikomuksesi ja jäsentää ja tallentaa päivämäärä oikein. Käytä 'Joskus se on on tärkeää tietää aikavyöhyke jossa tapahtuma tapahtui, ja muuntaminen yhdeksi aikavyöhykkeeksi hävittää peruuttamattomasti kyseisen tiedon. 'Jos teet markkinointikampanjaa ja haluat tietää, mitkä asiakkaat ovat tehneet tilauksia lounasaikaan, tilauksesta, joka näyttää olevan tehty keskipäivällä GMT, ei ole kovin hyötyä, kun se todella tehtiin aamiaisella New Yorkissa.' Jos kohtaat tällaisen tilanteen, olisi viisaampaa säästää myös paikallinen aika. Kuten tavallista, haluaisimme luoda päivämäärän ISO-muodossa, mutta meidän on ensin löydettävä aikavyöhykkeen siirtymä. Päivämäärä-objektin Aikavyöhykkeelleni +05: 45 saan -345, tämä ei ole vain päinvastainen merkki, mutta luku -345 voi olla täysin hämmentävä taustakehittäjälle. Joten muunnamme tämän arvoksi +05: 45. Nyt saamme loput arvoista ja luomme kelvollisen ISO-merkkijonon, joka edustaa paikallista DateTime-aikaa. Halutessasi voit kääri UTC: n ja paikalliset päivämäärät esineeseen. Jos haluat nyt selvittää, onko tapahtuma tapahtunut ennen keskipäivää paikallista aikaa, voit jäsentää päivämäärän ja käyttää Emme käyttäneet Joskus, vaikka paikallinen aikavyöhyke olisi tallennettu, haluat näyttää päivämäärät tietyllä aikavyöhykkeellä. Esimerkiksi tapahtumien ajat saattavat olla järkevämpiä nykyisen käyttäjän aikavyöhykkeellä, jos ne ovat virtuaalisia, tai aikavyöhykkeellä, jolla ne fyysisesti tapahtuvat, jos niitä ei ole. Joka tapauksessa kannattaa etsiä etukäteen vakiintuneita ratkaisuja muotoilulle nimenomaisilla aikavyöhykenimillä. Määritä palvelimet ja tietokannat aina käyttämään UTC-aikavyöhykettä. (Huomaa, että UTC ja GMT ovat ei sama asia - Esimerkiksi GMT saattaa tarkoittaa siirtymistä BST: ään kesällä, kun taas UTC ei koskaan.) Olemme jo nähneet, kuinka paljon kivun aikavyöhykekonversioita voi olla, varsinkin kun ne ovat tahattomia. Aina lähettämällä UTC DateTime ja määrittämällä palvelimesi UTC-aikavyöhykkeelle, elämäsi voi olla helpompaa. Taustakoodisi on paljon yksinkertaisempi ja puhtaampi, koska sen ei tarvitse tehdä mitään aikavyöhykkeen muunnoksia. DateTime-tietoja, jotka tulevat palvelimilta ympäri maailmaa, voidaan verrata ja lajitella vaivattomasti. Koodin takana pitäisi pystyä olettamaan palvelimen aikavyöhykkeen olevan UTC (mutta siinä on oltava vielä sisäänkirjautuminen varmistaakseen). Yksinkertainen kokoonpanon tarkistus säästää muunnosten muokkaamista ja koodaamista aina, kun uusi DateTime-koodi kirjoitetaan. Päivämäärän manipulointi on vaikea ongelma. Tämän artikkelin käytännön esimerkkien taustalla olevat käsitteet ovat JavaScriptiä laajempia, ja ne ovat vasta alkua DateTime-tietojen ja laskelmien oikeaan käsittelyyn. Lisäksi jokaisen auttajakirjaston mukana tulee oma sarja vivahteita. Alarivi on: Käytä ISO-taustapäätä ja jätä käyttöliittymä alustamaan asiat oikein käyttäjälle. Ammattitaitoiset ohjelmoijat ovat tietoisia joistakin vivahteista ja käyttävät (sitäkin selvemmin) hyvin tuettuja DateTime-kirjastoja sekä takana että käyttöliittymässä. Sisäänrakennetut toiminnot tietokannan puolella ovat toinen tarina, mutta toivottavasti tämä artikkeli antaa tarpeeksi taustaa tehdäksesi viisaampia päätöksiä myös tässä yhteydessä.Päivämäärän jäsentäminen
Date.now()
const date1 = new Date('Wed, 27 July 2016 13:30:00'); const date2 = new Date('Wed, 27 July 2016 07:45:00 UTC'); const date3 = new Date('27 July 2016 13:30:00 UTC+05:45');
const date = new Date(2016, 6, 27, 13, 30, 0);
const date = new Date('2016-07-27T07:45:00Z');
const date1 = new Date('25 July 2016'); const date2 = new Date('July 25, 2016');
Päivämäärän muotoilu
new Date('25 July 2016').getTime() !== new Date('2016-07-25').getTime() new Date('2016-07-25').getTime() === new Date('2016-07-25T00:00:00Z').getTime()
nimiavaruus, joka tekee päivämäärän muotoilusta yksinkertaisen toiminnan.Intl
ja Date
, joka on alustettu lähtöasetuksillamme. Oletetaan, että haluaisimme käyttää amerikkalaista muotoa (M / D / YYYY), tämä näyttää tältä:Intl.DateTimeFormat
const firstValentineOfTheDecade = new Date(2020, 1, 14); // 1 for February const enUSFormatter = new Intl.DateTimeFormat('en-US'); console.log(enUSFormatter.format(firstValentineOfTheDecade)); // 2/14/2020
rakentaja:DateTimeFormat
const nlBEFormatter = new Intl.DateTimeFormat('nl-BE'); console.log(nlBEFormatter.format(firstValentineOfTheDecade)); // 14/2/2020
const longEnUSFormatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); console.log(longEnUSFormatter.format(firstValentineOfTheDecade)); // February 14, 2020
: n voimassa olevat arvot ovat vain tämän kirjoituksen ovat day
tai 'numeric'
. Lainaus Flavio Copesin versio / Mathias Bynensin koodi hyödyntämään '2-digit'
toisen osan tätä varten voimme mukauttaa kuukauden päivän tuotoksen Intl
:formatToParts()
const pluralRules = new Intl.PluralRules('en-US', { type: 'ordinal' }) const suffixes = { 'one': 'st', 'two': 'nd', 'few': 'rd', 'other': 'th' } const convertToOrdinal = (number) => `${number}${suffixes[pluralRules.select(number)]}` // At this point: // convertToOrdinal('1') === '1st' // convertToOrdinal('2') === '2nd' // etc. const extractValueAndCustomizeDayOfMonth = (part) => { if (part.type === 'day') { return convertToOrdinal(part.value); } return part.value; }; console.log( longEnUSFormatter.formatToParts(firstValentineOfTheDecade) .map(extractValueAndCustomizeDayOfMonth) .join('') ); // February 14th, 2020
Internet Explorer (IE) ei tue lainkaan tämän kirjoituksen aikana, mutta kaikkia muita työpöytä-, mobiili- ja back-end (eli Node.js) -tekniikoita ei ole tukea . Niille, joiden on tuettava IE: tä ja jotka ehdottomasti tarvitsevat ordinaaleja, alla oleva sivulause (tai parempi, oikea päivämääräkirjasto) antaa vastauksen.formatToParts
Pythonissa tai PHP: ssä.strftime
antaa sinulle strftime('Today is %b %d %Y %X', mktime(5,10,0,12,30,99))
.Today is Dec 30 1999 05:10:00
saada päivämäärä eri muodoissa. (Varo, ettei kaikilla kielillä anneta samaa merkitystä kullekin kirjaimelle - varsinkin M ja M voidaan vaihtaa minuutteihin ja kuukausiin.)%
var currentDate = new Date(); var date = currentDate.getDate(); var month = currentDate.getMonth(); var year = currentDate.getFullYear();
var monthDateYear = (month+1) + '/' + date + '/' + year;
function pad(n) { return n<10 ? '0'+n : n; }
var mmddyyyy = pad(month + 1) + '/' + pad(date) + '/' + year;
var ddmmyyyy = pad(date) + '-' + pad(month + 1) + '-' + year;
var monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; var dateWithFullMonthName = monthNames[month] + ' ' + pad(date) + ', ' + year;
joka palauttaa 1. sijalle 1, 12. sijalle 12 ja 103. sijalle 103 jne., ja loput ovat yksinkertaisia:ordinal
var ordinalDate = ordinal(date) + ' ' + monthNames[month] + ', ' + year;
Päivämäärän muodon muuttaminen
var daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; ordinalDateWithDayOfWeek = daysOfWeek[currentDate.getDay()] + ', ' + ordinalDate;
JavaScript Date Objectin lokalisointitoimintojen käyttäminen
const myDate = new Date('Jul 21, 2013'); const dayOfMonth = myDate.getDate(); const month = myDate.getMonth(); const year = myDate.getFullYear(); function pad(n) { return n<10 ? '0'+n : n } const ddmmyyyy = pad(dayOfMonth) + '-' + pad(month + 1) + '-' + year; // '21-07-2013'
objektin Date
menetelmä:toLocaleDateString()
const today = new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric', });
.26 Jul 2016
-pohjainen tekniikka toimii hyvin samankaltaisesti kuin tämä, mutta antaa sinun käyttää muotoilijaobjektia uudelleen niin, että sinun on asetettava asetukset vain kerran.Intl.DateTimeFormat
-Toiminnon avulla on hyvä tapa siirtää muotoiluvaihtoehdot aina, vaikka tulostus näyttää hyvältä tietokoneellasi. Tämä voi suojata käyttöliittymää rikkomasta odottamattomia paikkoja, joilla on todella pitkät kuukausinimet, tai näyttämään hankalalta lyhyiden sijaintien vuoksi.toLocaleDateString()
const today = new Date().toLocaleDateString(undefined, { day: 'numeric', month: 'numeric', year: 'numeric', });
. Jos haluat varmistaa, että kuussa ja päivämäärässä on kaksi numeroa, muuta vain asetuksia:7/26/2016
const today = new Date().toLocaleDateString(undefined, { day: '2-digit', month: '2-digit', year: 'numeric', });
. Juuri mitä halusimme!
Koodi Tuotos Kuvaus 07/26/2016
'4:21:38 AM' Näytä vain ajan lokalisoitu versio now.toLocaleTimeString()
'04: 21: 38 AM ' Näytä lokalisoitu aika annettujen vaihtoehtojen perusteella now.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit', });
'' 22.7.2016, 4:21:38 AM '' Näytä käyttäjän kielen päivämäärä ja kellonaika now.toLocaleString()
'' 22.7.2016, 04.21 '' Näytä lokalisoitu päivämäärä ja kellonaika annettujen vaihtoehtojen perusteella Suhteellisten päivämäärien ja aikojen laskeminen
now.toLocaleString(undefined, { day: 'numeric', month: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', });
const myDate = new Date('July 20, 2016 15:00:00'); const nextDayOfMonth = myDate.getDate() + 20; myDate.setDate(nextDayOfMonth); const newDate = myDate.toLocaleString();
sisältää lokalisoidun merkkijonon, joka edustaa kyseistä päivämäärää. Selaimessani newDate
sisältää “8.8.2016 klo 15.00”.newDate
ja Date.getTime()
työskennellä kokonaislukujen kanssa, jotka edustavat millisekuntien lukumäärää tietystä aikakaudesta - nimittäin 1. tammikuuta 1970 lähtien. Jos esimerkiksi haluat tietää, milloin on nyt 17 tuntia tämän jälkeen:Date.setTime()
Päivämäärien vertaaminen
const msSinceEpoch = (new Date()).getTime(); const seventeenHoursLater = new Date(msSinceEpoch + 17 * 60 * 60 * 1000);
const date1 = new Date('July 19, 2014'); const date2 = new Date('July 28, 2014'); if(date1 > date2) { console.log('First date is more recent'); } else { console.log('Second date is more recent'); }
const date1 = new Date('June 10, 2003'); const date2 = new Date(date1); const equalOrNot = date1 == date2 ? 'equal' : 'not equal'; console.log(equalOrNot);
.not equal
date1.getTime() == date2.getTime()
const userEnteredString = '12/20/1989'; // MM/DD/YYYY format const dateStringFromAPI = '1989-12-20T00:00:00Z'; const dateFromUserEnteredString = new Date(userEnteredString) const dateFromAPIString = new Date(dateStringFromAPI); if (dateFromUserEnteredString.getTime() == dateFromAPIString.getTime()) { transferOneMillionDollarsToUserAccount(); } else { doNothing(); }
luo päivämäärän 1989-12-20T00: 00: 00 + 5: 45 tai 1989-12-19T18: 15: 00Z, joka ei ole sama kuin 1989-12-20T00: 00: 00Z aikaleiman suhteen.
new Date ('12/20/1989')
const userEnteredDate = '12/20/1989'; const parts = userEnteredDate.split('/'); const userEnteredDateISO = parts[2] + '-' + parts[0] + '-' + parts[1]; const userEnteredDateObj = new Date(userEnteredDateISO + 'T00:00:00Z'); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDateObj.getTime() == dateFromAPI.getTime(); // true
const userEnteredDate = new Date('1989-12-20'); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDate.getTime() == dateFromAPI.getTime(); // true
Kahden päivämäärän välisen eron löytäminen
Kahden päivämäärän välisten päivien määrän löytäminen
const userEnteredDate = new Date('12/20/1989'); const userEnteredDateTimeStamp = Date.UTC(userEnteredDate.getFullYear(), userEnteredDate.getMonth(), userEnteredDate.getDate(), 0, 0, 0); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDateTimeStamp == dateFromAPI.getTime(); // true ...
Käyttäjän iän löytäminen syntymäpäivästä
const dateFromAPI = '2016-02-10T00:00:00Z'; const now = new Date(); const datefromAPITimeStamp = (new Date(dateFromAPI)).getTime(); const nowTimeStamp = now.getTime(); const microSecondsDiff = Math.abs(datefromAPITimeStamp - nowTimeStamp); // Math.round is used instead of Math.floor to account for certain DST cases // Number of milliseconds per day = // 24 hrs/day * 60 minutes/hour * 60 seconds/minute * 1000 ms/second const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60 * 24)); console.log(daysDiff);
const birthDateFromAPI = '12/10/1989';
Ehdotuksia päivämäärän helvetin välttämiseksi
Päivämäärän ja kellonajan saaminen käyttäjältä
const parts = birthDateFromAPI.split('/'); const birthDateISO = parts[2] + '-' + parts[0] + '-' + parts[1]; const birthDate = new Date(birthDateISO); const today = new Date(); let age = today.getFullYear() - birthDate.getFullYear(); if(today.getMonth()
Date
muoto, vaikka sinulla olisi jo päivämäärä kelvollisessa jäsennettävässä muodossa. Jos kaikki tiimisi ohjelmoijat noudattavat tätä yksinkertaista sääntöä, koodin ylläpito pitkällä aikavälillä on erittäin helppoa, koska se on yhtä selkeä kuin voit olla new Date(year, month, day, hours, minutes, seconds, milliseconds)
rakentaja.Date
on sama kuin new Date(2012, 10, 12)
koska määrittelemättömät parametrit ovat oletusarvoisesti nolla.new Date(2012, 10, 12, 0, 0, 0, 0)
Vain päivämäärän saaminen
const dateFromPicker = '2012-10-12'; const timeFromPicker = '12:30'; const dateParts = dateFromPicker.split('-'); const timeParts = timeFromPicker.split(':'); const localDate = new Date(dateParts[0], dateParts[1]-1, dateParts[2], timeParts[0], timeParts[1]);
const dateFromPicker = '12/20/2012'; const dateParts = dateFromPicker.split('/'); const ISODate = dateParts[2] + '-' + dateParts[0] + '-' + dateParts[1]; const birthDate = new Date(ISODate).toISOString();
objektin syötteen ollessa kelvollisessa ISO-päivämäärämuodossa (VVVV-KK-PP), se on oletusarvoisesti UTC eikä selaimen aikavyöhykettä.Päivämäärän tallentaminen
Date
tai toISOString()
Date-objektin menetelmät muuntaa paikallinen DateTime UTC: ksi.toJSON()
Päivämäärän ja kellonajan näyttäminen
const dateFromUI = '12-13-2012'; const timeFromUI = '10:20'; const dateParts = dateFromUI.split('-'); const timeParts = timeFromUI.split(':'); const date = new Date(dateParts[2], dateParts[0]-1, dateParts[1], timeParts[0], timeParts[1]); const dateISO = date.toISOString(); $.post('http://example.com/', {date: dateISO}, ...)
esine.Date
tai toLocaleString()
ja toLocaleDateString()
menetelmiä tai päivämääräkirjastoa paikallisen ajan näyttämiseksi.toLocaleTimeString()
Milloin sinun tulisi tallentaa myös paikallista aikaa?
const dateFromAPI = '2016-01-02T12:30:00Z'; const localDate = new Date(dateFromAPI); const localDateString = localDate.toLocaleDateString(undefined, { day: 'numeric', month: 'short', year: 'numeric', }); const localTimeString = localDate.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit', });
funktio kertoo kuinka monta minuuttia se lisättynä tiettyyn paikalliseen aikaan antaa vastaavan UTC-ajan. Ehdotan sen muuntamista (+ -) hh: mm-muotoon, koska se tekee selvemmäksi, että se on aikavyöhykkeen siirtymä.getTimeZoneOffset()
const now = new Date(); const tz = now.gettime zoneOffset();
const sign = tz > 0 ? '-' : '+'; const hours = pad(Math.floor(Math.abs(tz)/60)); const minutes = pad(Math.abs(tz)%60); const tzOffset = sign + hours + ':' + minutes;
const localDateTime = now.getFullYear() + '-' + pad(now.getMonth()+1) + '-' + pad(now.getDate()) + 'T' + pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds());
const eventDate = { utc: now.toISOString(), local: localDateTime, tzOffset: tzOffset, }
toiminto.getHours()
const localDateString = eventDate.local; const localDate = new Date(localDateString); if(localDate.getHours() <12) { console.log('Event happened before noon local time'); }
täällä, mutta säilytämme silti sitä, koska tarvitsemme sitä tulevaisuudessa virheenkorjausta varten. Voisit itse asiassa lähettää vain aikavyöhykkeen siirtymän ja UTC-ajan. Mutta haluan tallentaa myös paikallisen ajan, koska joudut lopulta tallentamaan päivämäärän tietokantaan, ja paikallisen ajan tallentaminen erikseen antaa sinun tehdä kyselyn suoraan kentän perusteella sen sijaan, että sinun tarvitsisi suorittaa laskelmia paikallisen päivämäärän saamiseksi.Palvelimen ja tietokannan kokoonpano
On aika paremmalle päivämäärän käsittelylle