Top Banner
Java 8 Date/Time API Vaidas Pilkauskas
62

Java 8 Date/Time API (Lithuanian)

May 26, 2015

Download

Technology

vilniusjug

Presentation of Old/New Date/Time APIs in JDK8
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java 8 Date/Time API (Lithuanian)

Java 8 Date/Time APIVaidas Pilkauskas

Page 2: Java 8 Date/Time API (Lithuanian)

• 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

Page 3: Java 8 Date/Time API (Lithuanian)

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.

Page 4: Java 8 Date/Time API (Lithuanian)

Iki JDK8

Page 5: Java 8 Date/Time API (Lithuanian)

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

Page 6: Java 8 Date/Time API (Lithuanian)

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

Page 7: Java 8 Date/Time API (Lithuanian)

Nesilaikoma equals kontrakto

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

Page 8: Java 8 Date/Time API (Lithuanian)

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();

Page 9: Java 8 Date/Time API (Lithuanian)

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

Page 10: Java 8 Date/Time API (Lithuanian)

Nuo JDK8

Page 11: Java 8 Date/Time API (Lithuanian)

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

Page 12: Java 8 Date/Time API (Lithuanian)

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

Page 13: Java 8 Date/Time API (Lithuanian)

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

Page 14: Java 8 Date/Time API (Lithuanian)

Kuo daugiau galvojame apie laiką...

Page 15: Java 8 Date/Time API (Lithuanian)

Per daug savokų

• Tiek daug laiko savokų

• Pats “laikas” turi daug reikšmių

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

Page 16: Java 8 Date/Time API (Lithuanian)

Du pagrindiniai reikalavimai

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

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

Page 17: Java 8 Date/Time API (Lithuanian)

Mašinos skalė

Page 18: Java 8 Date/Time API (Lithuanian)

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ų

Page 19: Java 8 Date/Time API (Lithuanian)

Trukmė - Duration

• Laiko “kiekis” (amount)

• Nepriklauso nuo laiko linijos

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

Page 20: Java 8 Date/Time API (Lithuanian)

// 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);

Page 21: Java 8 Date/Time API (Lithuanian)

Tikslumas & keliamosios sekundės

Page 22: Java 8 Date/Time API (Lithuanian)

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

Page 23: Java 8 Date/Time API (Lithuanian)

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ė?

Page 24: Java 8 Date/Time API (Lithuanian)

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

Page 25: Java 8 Date/Time API (Lithuanian)

Žmogaus skalė

Page 26: Java 8 Date/Time API (Lithuanian)

Ž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

Page 27: Java 8 Date/Time API (Lithuanian)

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

Page 28: Java 8 Date/Time API (Lithuanian)

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

Page 29: Java 8 Date/Time API (Lithuanian)

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

Page 30: Java 8 Date/Time API (Lithuanian)

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

Page 31: Java 8 Date/Time API (Lithuanian)

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

Page 32: Java 8 Date/Time API (Lithuanian)

Kitos klasės

• Year

• YearMonth

• MonthDay

• Month - enum

• DayOfWeek - enum

• OffsetTime - local time + zone-offset

Page 33: Java 8 Date/Time API (Lithuanian)

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();

Page 34: Java 8 Date/Time API (Lithuanian)

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);

Page 35: Java 8 Date/Time API (Lithuanian)

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());

Page 36: Java 8 Date/Time API (Lithuanian)

Laiko zonos

Page 37: Java 8 Date/Time API (Lithuanian)

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į."

Page 38: Java 8 Date/Time API (Lithuanian)

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

Page 39: Java 8 Date/Time API (Lithuanian)

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

Page 40: Java 8 Date/Time API (Lithuanian)

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

Page 41: Java 8 Date/Time API (Lithuanian)

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()) { ... }

}

Page 42: Java 8 Date/Time API (Lithuanian)

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

Page 43: Java 8 Date/Time API (Lithuanian)

Integracija

Page 44: Java 8 Date/Time API (Lithuanian)

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)

Page 45: Java 8 Date/Time API (Lithuanian)

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

Page 46: Java 8 Date/Time API (Lithuanian)

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

Page 47: Java 8 Date/Time API (Lithuanian)

Kalendoriai

Page 48: Java 8 Date/Time API (Lithuanian)

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

Page 49: Java 8 Date/Time API (Lithuanian)

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)

Page 50: Java 8 Date/Time API (Lithuanian)

Kalendorių chronologijos

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

• ChronoLocalDate

• ChronoLocalDateTime

• ChronoZonedDateTimeo laikas yra standartinis LocalTime

Page 51: Java 8 Date/Time API (Lithuanian)

Here be dragons!

• Dirbti su kitais kalendoriais sudėtinga

• Daug ISO prielaidų negalioja

• Lengva suklysti

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

• Taigi...

Page 52: Java 8 Date/Time API (Lithuanian)

Here be dragons!

• Naudokite ISO, ne Chrono klases

• See ChronoLocalDate Javadoc paaiškinimą

• Nesaugokite kalendoriaus visoje sistemoje

• Kalendorius naudotojo profilio dalis

• Konvertuokite atvaizduodami UI

Page 53: Java 8 Date/Time API (Lithuanian)

Kas liko

Page 54: Java 8 Date/Time API (Lithuanian)

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);

Page 55: Java 8 Date/Time API (Lithuanian)

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

Page 56: Java 8 Date/Time API (Lithuanian)

Dabartinis laikas - Current time

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

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

Page 57: Java 8 Date/Time API (Lithuanian)

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));

Page 58: Java 8 Date/Time API (Lithuanian)

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

}

}

}

Page 59: Java 8 Date/Time API (Lithuanian)

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ų

Page 60: Java 8 Date/Time API (Lithuanian)

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);

Page 61: Java 8 Date/Time API (Lithuanian)

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!

Page 62: Java 8 Date/Time API (Lithuanian)

Summary

• JSR-310 naujas JDK8 Date/Time API

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

• http://threeten.github.com