44
Krótka historia czasu Tomasz Nurkiewicz | 20130706T11:40:00.000Z [email protected] @tnurkiewicz

Krótka historia czasu - Confitura 2013

Embed Size (px)

DESCRIPTION

Jaka jest różnica czasu między Warszawą a Sydney? Odpowiedź na to pytanie jest zaskakująco trudna. Równie zaskakującym jest jak wielu programistów tej trudności nie dostrzega. Niby po co? Bo niemal co roku na światło dziennie wypływają zawstydzające błędy w oprogramowaniu, wynikające z niewiedzy bądź lekkomyślnego traktowania... czasu w systemach komputerowych. Podczas tej prezentacji spróbuję pokazać, jak ważne jest świadome operowanie czasem podczas pisania oprogramowania. Nie będziemy (prawie) narzekali na klasę java.util.Date, ale skupimy się na fundamentalnych nieporozumieniach i błędach. Zobaczymy w przykładach fatalne skutki beztroskiego i nieumiejętnego obchodzenia się z czasem. Nauczymy się także jak przechowywać, przesyłać i przetwarzać czas oraz jak testować systemy zależne od czasu (czyli w zasadzie wszystkie). Nie spodziewajcie się eksploracji takiego czy innego API. Skupimy się raczej na zrozumieniu praw rządzących upływem czasu i ich odpowiednim modelowaniem w naszych programach.

Citation preview

Page 1: Krótka historia czasu - Confitura 2013

Krótka historia czasuTomasz Nurkiewicz

 | 2013­07­06T11:40:00.000Z

[email protected] @tnurkiewicz

Page 2: Krótka historia czasu - Confitura 2013

Tomasz Nurkiewicz | 

6+ lat z JavąScala, JavaScript, Clojure...Back­end, analiza i wizualizacja danych

 | Niegdyś aktywny na Trzeci raz na Javarsovii/ConfiturzePracuję w Oslo ( )

nurkiewicz.blogspot.com

[email protected] @tnurkiewicz

scala.net.pl github.com/nurkiewiczStackOverflow

we are hiring!

Page 3: Krótka historia czasu - Confitura 2013

Zły dzień Microsoftu

 blogs.msdn.com/b/windowsazure/archive/2012/03/09/summary­of­windows­azure­service­disruption­on­feb­29th­2012.aspx

Page 4: Krótka historia czasu - Confitura 2013

Wynik programu?Java:

C#:

Calendar cal = new GregorianCalendar(2012, FEBRUARY, 29, 15, 0);cal.add(YEAR, 1);System.out.println(cal.getTime());

DateTime cal = new DateTime(2012, 2, 29, 15, 0, 0).AddYears(1);Console.WriteLine(cal);

Page 5: Krótka historia czasu - Confitura 2013

28. lutego 2013, 15:0029. lutego 2013, 15:001. marca 2013, 00:001. marca 2013, 15:00IllegalArgumentException

Page 6: Krótka historia czasu - Confitura 2013

True story“[...] zgodnie z Regulaminem [...] odsetki nalicza się za faktyczną

liczbę dni pozostawania środków na koncie [...] z tym, żeprzyjmuje się, że rok liczy 365 dni.Rok 2012 liczy 366 dni, dlatego też 

odsetki za dzień 29 lutego nie naliczają się.Z serdecznymi pozdrowieniami, [pewien] Bank”

samcik.blox.pl/2012/03/Dzien­ktorego­nie­ma­Sprawdz­co­bank­wykreslil.html

Page 7: Krótka historia czasu - Confitura 2013

Zła sekunda Linuksa

 www.greenprophet.com/2012/07/leap­second­bug­consumes­megawatts­of­electricity/

Page 8: Krótka historia czasu - Confitura 2013

Sekundy przestępne

 en.wikipedia.org/wiki/Leap_second

Page 9: Krótka historia czasu - Confitura 2013

Inne błędyProblem roku 2000 (Y2K)Problem roku 2011 (Taiwan)Problem roku 2038 (Integer.MAX_VALUE)Problem roku 2042 (IBM S/370)Problem roku 2107 (MS­DOS FAT)Problem 9. września '99 (9/9/99)

en.wikipedia.org/wiki/Time_formatting_and_storage_bugs

Page 10: Krótka historia czasu - Confitura 2013

Zrozumieć domenę problemu...każdego

Page 11: Krótka historia czasu - Confitura 2013

Reprezentacja czasu

 www.edali.org/persistence­of­memory.jsp

Page 12: Krótka historia czasu - Confitura 2013

Ilość sekund od arbitralnego momentuSystem kalendarzowy

Page 13: Krótka historia czasu - Confitura 2013

Oś czasu

Page 14: Krótka historia czasu - Confitura 2013

Czas "0"?Data Wykorzystywana w

0. stycznia 0 MATLAB

1. stycznia 0 Symbian, Turbo DB

1. stycznia 1 Microsoft .NET, Go

1. stycznia 1601 NTFS, COBOL, Win32/Win64

1. stycznia 1753 Microsoft SQL Server

31. grudnia 1840 MUMPS

17. listopada 1858 VMS, United States Naval Observatory, DVB SI, astronomia

30. grudnia 1899 Microsoft COM DATE, Object Pascal

0. stycznia 1900 Microsoft Excel, Lotus 1­2­3

1. stycznia 1900 NTP, IBM CICS, Mathematica, RISC OS, Common Lisp

1. stycznia 1904 LabVIEW, Mac OS 9, Palm OS, MP4

1. stycznia 1950 SEGA Dreamcast

Data Wykorzystywana w

1. stycznia 1960 S­Plus, SAS

31. grudnia 1967 Pick OS

1. stycznia 1970 Linux, Mac OS X, C, Java, JavaScript,

Perl, PHP, Python, Tcl, ActionScript

1. stycznia 1978 AmigaOS

1. stycznia 1980 DOS, OS/2, FAT16 I FAT32, VOS

6. stycznia 1980 Qualcomm BREW, GPS

1. stycznia 1981 Acorn NetFS

1. stycznia 1984 CiA® CANopen®

22. sierpnia 1999 Satelita Galileo

1. stycznia 2000 PostgreSQL, AppleSingle, AppleDouble

1. stycznia 2001 Apple Cocoa  en.wikipedia.org/wiki/Epoch_date

Page 15: Krótka historia czasu - Confitura 2013

java.util.Date:

vs.:

en.wikipedia.org/wiki/Calendar_date“A date in a calendar is a reference to a particular day

represented within a calendar system. [...] A particular day maybe represented by a different date in another calendar”

docs.oracle.com/javase/7/docs/api/java/util/Date.html“The class Date represents a specific instant in time, with

millisecond precision.”

Page 16: Krótka historia czasu - Confitura 2013

Strefy czasowejava.util.Timezone

Page 17: Krótka historia czasu - Confitura 2013

Różnica czasu między Warszawą a Sydney?

 www.travel.com.hk/region/timezone.htm

Page 18: Krótka historia czasu - Confitura 2013

Czas letni (Daylight saving time)

 en.wikipedia.org/wiki/Daylight_saving_time

Page 19: Krótka historia czasu - Confitura 2013

Czas letni

Zima → Lato Lato → Zimaen.wikipedia.org/wiki/Daylight_saving_time

Page 20: Krótka historia czasu - Confitura 2013

...a zatem?

 www.travel.com.hk/region/timezone.htm

Page 21: Krótka historia czasu - Confitura 2013

Reprezentacja

ŹLE!final TimeZone tz = TimeZone.getTimeZone("Europe/Warsaw");

TimeZone.getTimeZone("GMT+01:00");

TimeZone.getTimeZone("Europe/warsaw");

Page 22: Krótka historia czasu - Confitura 2013

Data kalendarzowajava.util.Calendar

Page 23: Krótka historia czasu - Confitura 2013

Lata przestępne - ŹLE! def leapYear(year: Int): Boolean = year % 4 == 0

Page 24: Krótka historia czasu - Confitura 2013

Lata przestępne - od biedy def leapYear(year: Int): Boolean = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)

Page 25: Krótka historia czasu - Confitura 2013

Lata przestępne def leapYear(year: Int): Boolean = new GregorianCalendar(year, JANUARY, 1). getActualMaximum(DAY_OF_YEAR) > 365

Page 26: Krótka historia czasu - Confitura 2013

ZagadkaCalendar c = Calendar.getInstance();

System.out.println(c.get(Calendar.YEAR));

Page 27: Krótka historia czasu - Confitura 2013

Mamy (gregoriański) rok 2013

A tymczasem w Tajlandii...

...i w Japonii...

$ java ...2013

$ java -Duser.country=TH -Duser.language=th ...2556

$ java -Duser.country=JP -Duser.language=ja -Duser.variant=JP ...25

Page 28: Krótka historia czasu - Confitura 2013

Lepiej:

Jeszcze lepiej:

Na wszelki wypadek...

Calendar c = new GregorianCalendar();

Calendar c = new GregorianCalendar(timeZone);

Calendar c = new GregorianCalendar(timeZone, locale);

Page 29: Krótka historia czasu - Confitura 2013

Date czy Calendar?"...po innym zdarzeniu""...w ciągu 10 sekund""...w ciągu godziny""...w ciągu 24 godzin""...w ciągu jednego dnia""...w 2013 roku""...po 17:00""...w piątek"

Page 30: Krótka historia czasu - Confitura 2013

Praktyka

Page 31: Krótka historia czasu - Confitura 2013

Joda Timefinal DateTime yearLater = new DateTime(2012, 2, 29, 15, 0).plusYears(1);

joda­time.sourceforge.net

Page 32: Krótka historia czasu - Confitura 2013

Joda Time w JAX-WSimport org.joda.time.DateTime;import javax.xml.bind.DatatypeConverter;

public class XsdJodaTimeConverter { public static DateTime unmarshal(String dateTime) { final long millis = DatatypeConverter. parseDate(dateTime). getTimeInMillis(); return new DateTime(millis); }

public static String marshal(DateTime calendar) { return DatatypeConverter.printDate( calendar.toGregorianCalendar() ); }}

Page 33: Krótka historia czasu - Confitura 2013

JAX-WS: plik .xjb<bindings version="1.0" xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <globalBindings> <javaType xmlType="xs:dateTime" name="org.joda.time.DateTime" parseMethod="XsdJodaTimeConverter.unmarshal" printMethod="XsdJodaTimeConverter.marshal"/> </globalBindings></bindings>

Page 34: Krótka historia czasu - Confitura 2013

Joda Time w JPA 2.1import org.joda.time.Instant;import javax.persistence.AttributeConverter;import javax.persistence.Converter;import java.util.Date;

@Converter(autoApply = true)public class JodaTimeConverter implements AttributeConverter<Instant, Date> {

@Override public Date convertToDatabaseColumn(Instant attr) { return attr != null? attr.toDate(): null; }

@Override public Instant convertToEntityAttribute(Date dbData) { return dbData != null? new Instant(dbData): null; }}

Page 35: Krótka historia czasu - Confitura 2013

Testowanie - narzędziaKontrolowane źródło czasu ( )"Egzotyczna" domyślna strefa czasowaNie śpij! (Thread.sleep()), ScalaCheck

fake system clock

Awaitility

Page 36: Krótka historia czasu - Confitura 2013

Testowanie - przypadkiPoczątek/koniec miesiąca/rokuDni powszednie i weekendy29 lutegoStrefy czasowe, czas letni

Page 37: Krótka historia czasu - Confitura 2013

ScalaCheck i ScalaTest

Negatywny rezultat

implicit override val generatorDrivenConfig = PropertyCheckConfig(minSuccessful = 10000, workers = 4)

test("any date +1 year and -1 year should yield same date back") { check { random: Date => { val plusMinusYear = new GregorianCalendar plusMinusYear.setTime(random) plusMinusYear.add(YEAR, 1) plusMinusYear.add(YEAR, -1) random == plusMinusYear.getTime } }}

Falsified after 2665 passed tests: arg0 = Mon Feb 29 03:21:22 CET 73843340

Page 38: Krótka historia czasu - Confitura 2013

Zdarzenia w przyszłości,  , ...

QuartzJMS

Activiti jBPM

Page 39: Krótka historia czasu - Confitura 2013

Quartz schedulernewTrigger() .startAt(futureDate(1, YEAR)) .build();

quartz­scheduler.org/documentation/quartz­2.1.x/tutorials/tutorial­lesson­05

Page 40: Krótka historia czasu - Confitura 2013

JMS z opóźnieniemMessageProducer producer = session.createProducer(destination);TextMessage message = session.createTextMessage("...hello, delayed!");message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, oneYearMillis);producer.send(message);

http://activemq.apache.org/delay­and­schedule­message­delivery.html

Page 41: Krótka historia czasu - Confitura 2013

Bonus / Computus(defn easter [year] (let [ a (mod year 19) b (Math/floor (/ year 100)) c (mod year 100) d (Math/floor (/ b 4)) e (mod b 4) f (Math/floor (/ (+ b 8) 25)) g (Math/floor (/ (inc (- b f)) 3)) h (mod (+ (- (+ (* 19 a) b) d g) 15) 30) i (Math/floor (/ c 4)) k (mod c 4) L (mod (- (+ 32 (* 2 e) (* 2 i)) h k) 7) m (Math/floor (/ (+ a (* 11 h) (* 22 L)) 451)) n (- (+ h L 114) (* 7 m)) month (dec (Math/floor (/ n 31))) day (inc (mod n 31))] (java.util.GregorianCalendar. year month day)))

en.wikipedia.org/wiki/Computus

Page 42: Krótka historia czasu - Confitura 2013

Bugi, więcej bugów...1.  "Due to the lack of [time] synchronization [...] a car bomb went off [...] one hour earlier than

expected" ( )2.  "F­22 Raptors [...] experienced multiple computer crashes coincident with their crossing of

[...] the International Date Line" ( )3.  "Damage to a German steel facility occurred during a DST transition" (

)4. 

5. 6.  Niesłuszne posądzenie o defraudację i kradzież (

­ [37])7.  Katalog kilkuset błędów, stan na rok 2000 (!) ( )

catless.ncl.ac.uk/Risks/20.58.html#subj12

en.wikipedia.org/wiki/List_of_software_bugs

en.wikipedia.org/wiki/Daylight_Savings_Timewww.wired.com/wiredenterprise/2012/07/leap­second­bug­wreaks­havoc­with­java­linuxwww.theregister.co.uk/2012/07/02/leap_second_crashes_airlines

www.cs.tau.ac.il/~nachumd/horror.html

www.csl.sri.com/users/neumann/cal.html

Page 43: Krótka historia czasu - Confitura 2013

Przydatne i ciekawe1.   ­ wszystko o czasie2.   ­ czas uniksowy3.   ­ kanwa tej prezentacji4.   ­ definicje TAI, UT, UTC...5.   ­ Samoa and Tokelau skip a day for dateline

change

www.timeanddate.comwww.epochconverter.comwww.odi.ch/prog/design/datetime.phptycho.usno.navy.mil/systime.htmlwww.bbc.co.uk/news/world­asia­16351377

Page 44: Krótka historia czasu - Confitura 2013

Dziękuję za poświęcony... czas! 

Twitter: [email protected]

@tnurkiewicz

nurkiewicz.github.io/talks/confitura2013