Java 8 Date/Time API (Lithuanian)

Post on 26-May-2015

346 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Presentation of Old/New Date/Time APIs in JDK8

Transcript

Java 8 Date/Time APIVaidas Pilkauskas

• programuotojas

• pagrindinė kalba - Java

• domiuosi kitomis kalbomis - Scala, JavaScript, Python, Ruby

• Kai neprogramuoju - dviračiai, snieglentė, roko muzika, šiuolaikinis menas, Vilnius JUG

https://www.google.com/+VaidasPilkauskas

Legal

This work is licensed under the Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

Slides 10-62 are derived from The new JDK 1.8 Date and Time API – JSR-310 by Stephen Colebourne given at JAX 2013.

All the other slides are based on various publicly available internet resources listed at the end in the reference list.

Iki JDK8

Kodėl reikalingas naujas Date/Time API?

java.util.Date is a testament to the fact that even brilliant programmers can screw up.

java.util.Calendar, which Sun licensed to rectify the Date mess, is a testament to the fact that average programmers can screw up, too.

http://stackoverflow.com/questions/1571265/why-is-the-java-date-api-java-util-date-calendar-such-a-mess

java.util.Date

• Mutuojamas - galima keisti reikšmę

• Milisekundžių tikslumas nepakankamas

• new Date().getYear() //114

• Tinkamai nepalaiko laiko juostų

• Nėra patogių priemonių dirbti su intervalais

• Metai prasideda nuo 1900, mėnesio diena nuo 1, visa kita nuo 0)

Date date = new Date(1L);

date.toString();

//Thu Jan 01 02:00:00 EET 1970

Nesilaikoma equals kontrakto

Date date = new Date();Timestamp timeStamp = new Timestamp(date.getTime());date.equals(timeStamp); // truetimeStamp.equals(date); // false

java.util.Calendar

• Taip pat mutuojamas

• Nepatogus API

• Sunku pridėti naujus kalendorius

• Trūksta getterių paprastai datų informacijai

Calendar c = Calendar.getInstance();

int weekday = c.get(DAY_OF_WEEK);

Date d = c.getTime();

Joda-Time

Java ekosistemoje suvokiama kaip

“Kokybiška datos ir laiko biblioteka”

Tai kodėl ne Joda-Time yra Java 8 Date/Time API?

Nes nepakankamai tobula.

“Well, there is one key reason - Joda-Time has design flaws.“ - Stephen Colebourne

http://blog.joda.org/2009/11/why-jsr-310-isn-joda-time_4941.html

Nuo JDK8

JSR 310

• Nauja datos ir laiko biblioteka

• Sukurta visiškai nuo pradžių

• Įtakota Joda-Time, speco vienas iš vadovų - Stephen Colebourne

• Tai atviro kodo JSR projektas (palyginimui Joda-Time - atviro kodo biblioteka)o http://threeten.github.com/o Originalus kodas BSD (3 clause) licencijao OpenJDK kodas GPLo virš 20000 testų

• Yra nuportintas JDK7

Tikslai

• Išsamus datos/laiko modelis

• Dažnai sutinkamų kalendorių palaikymas

• Tipizavimaso vengti primityvų, kai yra prasmėo save dokumentuojantiso draugiškas IDE

• “Sutariantis” su egzistuojančiomis JDK datų/laiko klasėmis

• Atsižvelgti į XML ir SQL poreikius

Projektavimo principai

• Nekeičiamumas (Immutability)o thread-safe, tinka kešuoti, funkcinis programavimas

• Fluent APIo lengvai skaitomas, tarsi įprastas sakinys

• Švarus, aiškus, tikėtinaso gerai apibrėžti metodai, paprastas JavaDoco stipri būsenos kontrolė

• Plečiamaso JSR/JDK autoriai visko nežino

Kuo daugiau galvojame apie laiką...

Per daug savokų

• Tiek daug laiko savokų

• Pats “laikas” turi daug reikšmių

• Reikia apibrėžti nuoseklią srities kalbą!

Du pagrindiniai reikalavimai

• Tęstinis kompiuterio laikaso vienas didėjantis skaičiuso suprojektuotas kompiuteriui

• Žmogauso paremtas laukeliaiso metai, mėnuo, diena, valanda, minutė, sekundė

Mašinos skalė

Momentas - Instant

• Vienas momentinis taškas laiko linijoje

• Įvykio Timestampas

• Java class - Instanto matuojamas nanosekundėmis nuo 1970-01-01o apima visatos amžiaus įvykius o problema - nėra tinkamo primityvo - 96 bitų

Trukmė - Duration

• Laiko “kiekis” (amount)

• Nepriklauso nuo laiko linijos

• Java class - Durationo matuojamas nanosekundėmiso reikia 96 bitų

// instant

Instant start =

Instant.ofEpochMilli(123450L);

Instant end = Instant.now();

assert start.isBefore(end);

assert end.isAfter(start);

// duration

Duration duration = Duration.ofSeconds(12);

Duration bigger = duration.multipliedBy(4);

Duration biggest = bigger.plus(duration);

// combination

Instant later = start.plus(duration);

Instant earlier = start.minus(duration);

Tikslumas & keliamosios sekundės

Realybė• SI sekundė fiksuoto ilgio

• Diena ilgiai gali būti skirtingi

• Astronomai sako, kad Žemė lėtėja

• Diena != (24 valandos * 60 minutės * 60 SI sekundės)

• Realiai dienos ilgesnės nei 86400 SI sekundės

• UTC įterpia keliamąją sekundę, kad pataisytų dienos ilgį

• Kompiuteriai prastai palaiko keliamąsias sekundes

Java milisekundės

• Java skaičiuoja milisekundes nuo 1970-01-01

• Ką tai reiškia?

• Apibrėžimas netikslus, nes

• UTC pradėtas tik 1972-01-01o 1970-01-01 taigi, pradžios taškas labai nepatogus

• Apibrėžimas - 86400 sekundės per dienąo kas atsitinka toje vietoje, kur įterpiama keliamoji

sekundė?

Pasirinktas būdas• Apibrėžta Java laiko skalė, ir susieta su

civiliniu laiku

• Vidurdienis tiksliai atitinka civilinį laiką

• Visas kitas laikas kiek įmanoma tiksliau

• Diena padalinta į 86400 daleles - “sekundes”

• Java epocha prasideda 1970-01-01

• Tai reiškia, kad programuotojai gali ignoruoti keliamąsias sekundes

• Nieko naujo, tai UTC-SLS

• Tai tik apibrėžimas, viskas priklauso nuo OS

Žmogaus skalė

Žmogaus skalė

• Žmogaus data/laikaso paremtas laukeliaiso metai, mėnuo, diena, minutė, sekundėo 7 dienų savaitė, diena - 24 valandos

• Reikalavimaio Data ir laikaso Data be laikoo Laikas be datoso Laiko juostos skirtumas nuo UTCo Laiko zona

Vietos data - Local date

• Data be laiko ir laiko zonos

• pvz., gimtadienis

• pvz., šventinė diena, atostogų pradžia

• Java klasė - LocalDateo saugomi metai-mėnuo-diena

// 2014-03-12

Vietos laikas - Local time

• Laikas be datos ir laiko zonos

• pvz., parduotuvės atidarymo laikas

• pvz., laikas sieniniame laikrodyje

• Java klasė - LocalTimeo saugoma valanda-minutė-sekundė-nanosekundė

// 20:30

Vietos data su laiku - Local date-time

• Data su laiku be laiko zonos

• pvz., vietinis laikas, kada kyla lėktuvas

• Java klasė - LocalDateTimeo apjungia LocalDate & LocalTime

// 2014-03-12T20:30

Zonos poslinkis - Zone-offset

• Poslinkis valandomis ir minutėmis nuo UTC

• Lietuva priekyje UTC - teigiama reikšmė

• JAV atsilieka nuo UTC - neigiama reikšmė

• Java klasė - ZoneOffseto saugo sekundes -18:00 to +18:00 diapazone

// +01:00

Data ir laikas su poslinkiu - Offset date-time

• Data ir laikas su zonos poslinkiu

• pvz., audito įrašo timestampas su laiko zona

• Tas pats momentas - Instant, tik su papildoma poslinkio informacija

• Java class - OffsetDateTimeo apjungia LocalDateTime & ZoneOffset

// 2014-03-12T20:30+02:00

Kitos klasės

• Year

• YearMonth

• MonthDay

• Month - enum

• DayOfWeek - enum

• OffsetTime - local time + zone-offset

Užklausos

• Getteriai

• Metodai grąžina geriausią tipą tam laukuio daugumai laukų - primityvaio enumai savaitės dienai, mėnesiui

LocalDate date = LocalDate.of(2010, 12, 3);

int year = date.getYear();

Month month = date.getMonth();

int dom = date.getDayOfMonth();

boolean leap = date.isLeapYear();

int monthLen = date.lengthOfMonth();

Atnaujinimai

• Beveik viskas - nekintama (nemutuojama)

• Naudojamas 'with' metodas vietoje ‘set’o nekeičiamas originalus objektaso grąžinama nauja, patobulinta kopijao norint toliau naudoti, reikia išsisaugoti

LocalDate date = LocalDate.of(2010,Month.DECEMBER,3);

LocalDate later = date.withYear(2011);

LocalDate between = date.with(Month.MAY);

Derintojai - Adjusters

• Sudėtingesni pakeitimai gali būti atliekami Adjusterių pagalba, pvz.:o iš turimos datos gauti paskutinę mėnesio dienąo iš turimos datos gauti kitą antrą trečiadienį (kada

kitas JUGas?)

public interface TemporalAdjuster {

Temporal adjustInto(Temporal input);

}

LocalDate adjusted = date.with(lastDayOfMonth());

LocalDate adjusted = date.with(next2ndWednesday());

Laiko zonos

Laiko zonų apžvalga

• Pasaulis padalintas įvairias laiko zonas

• Vietovės laikas apibrėžiamas politinių taisykliųo Sirija pakeičia vasaros laiką (DST) su 3 dienų

perspėjimuo Vakarų Australija turėjo 3 metų DST eksperimentąo Brazilija keičia DST kasmeto Egiptas turėjo du DST periodus 2010

• Taisyklės apibrėžia laiko zonos poslinkio pasikeitimąo "Žiemą Lietuva bus 2 valandomis priekyje nuo UTC,

o vasarą jau 3. Laikas persukamas viena valanda į priekį paskutinį kovo sekmadienį ir atsukamas atgal paskutinį spalio sekmadienį."

Laiko zonų analizė

• Keletas grupių renka ir teikia informaciją apie TZ taisykleso IANA "Timezone database" (TZDB)o Windowso IATA - Tarptautinė oro transporto asociacija

• Kiekviena grupė apibrėžia savo identifikatorių

• TZDB naudoja 'Europe/Vilnius' Lietuvai

• Taisyklės apibrėžia ilgalaikius DST pakeitimus

• bei kada keičiasi poslinkis

Laiko zonų dizainas

• JDK javadoc:o “TimeZone represents a time zone offset, and also

figures out daylight savings”

• JSR-310 atskiria atsakomybeso ZoneOffset – nuo +14:00 iki -12:00o ZoneRules – poslinkių keitimo taisyklėso ZoneId – zonos identifikatorius, identifikuoja

vietą/valdžią

• Tik viena papildoma datos/laiko klasėo ZonedDateTime

Zonų laiko tarpai ir persidengimai

• Pavasario DST “tarpas”

• Rudens DST “persidengimas”

• JSR-310 nemeta exceptionų, o Joda-Time metao prasmingas datos interpretavimaso Pagal nutylėjimą - vasaros laikas

// one day before DST ends (overlap of one hour)

ZoneId zone = ZoneId.of("Europe/London");

ZonedDateTime dt = ZonedDateTime.of(2010, 10, 27, 1, 30, 0, 0, zone);

// dt = 2010-10-27 01:30 +01:00

dt = dt.plusDays(1);

// dt = 2010-10-28 01:30 +01:00

// retains the offset where possible

dt = dt.plusHours(1);

// dt = 2010-10-28 01:30 +00:00

// offset changes, same time

Galima pasitikrinti

ZoneId zone = ZoneId.of("Europe/London");

LocalDateTime ldt = LocalDateTime.of(2010,10,27,1,30);

ZoneOffsetTransition trn = zone.getRules().getTransition(ldt);

if (trn != null) {

if (trn.isGap()) { ... }

if (trn.isOverlap()) { ... }

}

Klasių santrauka

• LocalDate 2010-12-03

• LocalTime 11:05:30

• LocalDateTime 2010-12-03T11:05:30

• OffsetTime 11:05:30+01:00

• OffsetDateTime 2010-12-03T11:05:30+01:00

• ZonedDateTime 2010-12-03T11:05:30+01:00

Europe/Paris

• Year 2010

• YearMonth 2010-12

• MonthDay 12-03

• Instant 2576458258.266 epoch-seconds

Integracija

Egzistuojančios JDK klasės

• Date, Calendar, SQL kalsės ir TimeZoneo konvertavimo metodai į ir iš JSR-310 tipuso ne deprecated :(

• JSR-310 nepriklauso nuo senųjų klasių (teoriškai reiškia, kad kažkada galima bus išmesti senąsias klases)

ISO-8601

• Visos klasės ir toString() paremtos ISO-8601

• Pagrįstas Grigaliaus kalendoriumi

• Nusako, kaip skaičiais atvaizduoti datas/laikus

• Kitų internetinių standartų bazė, tokių kaip XMLo XML schema gerai atitinka JSR-310 klases

SQL duomenų bazės

• Klasės atitinka SQLo LocalDate DATEo LocalTime TIME WITHOUT TIME ZONEo LocalDateTime TIMESTAMP WITHOUT

TIMEZONEo OffsetTime TIME WITH TIME ZONEo OffsetDateTime TIMESTAMP WITH TIME

ZONE

• JDBC atnaujintas, kad atitiktų JSR-310

Kalendoriai

Calendar systems

• Bazinis kalendorius paremtas ISO-8601o dabartinis civilinis kalendoriuso istoriškai netikslus

katalikai - 1582 britai - 1752 rusai - 1917?

• Reikalavimaio JDK turi palaikyti įprastus kalendoriuso kalendorių palaikymas neturi pasunkinti API

naudojimoo nedviprasmiškas API

Regioninės kalendorių sistemos

• Dažniausiai naudojami ne ISO kalendoriaio Islamo, Japonų, Kinų, Budizmo ir kiti

• Pasiekiami pagal pavadinimą

• Pasiekiami pagal BCP-47 lokalės išplėtimąo th-TH-u-ca-buddhist

• Datos – era, metai, mėnuo, dienao mėnesių ilgiai & tvarka skiriasi

• Leidžiamos tik datos variacijoso ignoruojami kalendoriai pradedantys dieną skirtingu

metu (saulėtekis/saulėlydis)

Kalendorių chronologijos

• Chronology apibrėžia kalendoriaus sistemąo factory’is kurti datoms

• ChronoLocalDate

• ChronoLocalDateTime

• ChronoZonedDateTimeo laikas yra standartinis LocalTime

Here be dragons!

• Dirbti su kitais kalendoriais sudėtinga

• Daug ISO prielaidų negalioja

• Lengva suklysti

• Būtina daryti kodo peržiūras!

• Taigi...

Here be dragons!

• Naudokite ISO, ne Chrono klases

• See ChronoLocalDate Javadoc paaiškinimą

• Nesaugokite kalendoriaus visoje sistemoje

• Kalendorius naudotojo profilio dalis

• Konvertuokite atvaizduodami UI

Kas liko

Elementų kombinavimas

• Lengva apjungti datos ir laiko objektus

• Naudojant ‘at’

• taip vadinamas Fluent API

LocalDate date = Year.of(2013).atMonth(MARCH).atDay(27);

LocalDateTime dt = date.atTime(12, 30);

OffsetDateTime odt = dt.atOffset(ZoneOffset.ofHours(2));

ZoneId london = ZoneId.of("Europe/London");

ZonedDateTime zdt1 = date.atStartOfDay(london);

ZonedDateTime zdt2 = Instant.now().atZone(london);

Periodai - Periods

• Datos pagrindo laiko “kiekis” pasiekiamas žmogiškais laukaiso 6 metai, 2 mėnesiai ir 12 dienų

• Panaudojimo pvz.:o konferencijos ilgis – 5 dienoso nėštumas – 9 mėnesiai

• Java klasė - Periodo laukeliai metams, mėnesiams, dienoms

• galima atimti/pridėti prie datos/laiko

• Duration klasė - laiko ekvivalentas

Dabartinis laikas - Current time

• Priklauso nuo laiko zonoso dažnai tai pamirštame

• Reikalavimaio sustabdyti laiką testuoseo pakeisti laiką į praeitį/ateitįo pristabdyti/paspartinti

Dabartinis laikas - Current time

• Pasiekti esamą laiką naudojant objektąo vengti Singletono Inversion of Control

• Galima implementuoti subklasęo taigi - kontroliuoti laiką :)

// system millis, default time zone

Instant instant = Instant.now(Clock.system());

LocalDate date = LocalDate.now(Clock.system());

// system millis, specified time zone

ZoneId zone = ZoneId.of("Europe/Moscow");

LocalDate date = LocalDate.now(Clock.system(zone));

Dabartinis laikas - Current time

• Palaiko Inversion of Controlo inject Clocko galima turėti 'stop time' subklasę testavimui

public class MyForm {

@Inject

private Clock clock; // inject with Spring/Guice

public void validate(LocalDate date) {

if (date.isBefore(LocalDate.now(clock))) {

// error

}

}

}

Formatting and Parsing

• toString() grąžina ISO-8601

• Formatavimas/parsinimas palaiko šablonuso kaip kad SimpleDateFormato taip pat sudėtingesnius formatus

• pagrindinė formatavimo klasė - DateTimeFormatter

• Pateikia daug įprastų formaterių

Amount between

• Lengva suskaičiuoti laikotarpį tarp dviejų datų/laikų

• Pagal vienetus

• Arba visą periodą/trukmę (Period/Duration)

LocalDate date1 = LocalDate.of(2012, 3, 4);

LocalDate date2 = LocalDate.of(2013, 1, 26);

// Duration

long days = DAYS.between(date1, date2);

// Period

Period period = Period.between(date1, date2);

Plėtimo galimybės

• Plečiama 5 būdais, parašant savoo datos/laiko klasęo kiekio (amount) klasęo datos/laiko laukeliuso datos/laiko vienetuso kalendorių

• Nepamiršti apie Javadoc kontraktus!

Summary

• JSR-310 naujas JDK8 Date/Time API

• Išbandykite JDK 8 buildą arba JDK 7 backportą

• http://threeten.github.com

top related