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.
14. 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 123
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 SPlus, 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
21. Reprezentacja
ŹLE!
final TimeZone tz = TimeZone.getTimeZone("Europe/Warsaw");
TimeZone.getTimeZone("GMT+01:00");
TimeZone.getTimeZone("Europe/warsaw");
26. Zagadka
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.YEAR));
27. 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
28. Lepiej:
Jeszcze lepiej:
Na wszelki wypadek...
Calendar c = new GregorianCalendar();
Calendar c = new GregorianCalendar(timeZone);
Calendar c = new GregorianCalendar(timeZone, locale);
31. Joda Time
final DateTime yearLater = new DateTime(2012, 2, 29, 15, 0).plusYears(1);
jodatime.sourceforge.net
32. Joda Time w JAX-WS
import 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()
);
}
}
37. 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
41. 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
42. Bugi, więcej bugów...
1. "Due to the lack of [time] synchronization [...] a car bomb went off [...] one hour earlier than
expected" ( )
2. "F22 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_Time
www.wired.com/wiredenterprise/2012/07/leapsecondbugwreakshavocwithjava
linux
www.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
43. Przydatne i ciekawe
1. wszystko o czasie
2. czas uniksowy
3. kanwa tej prezentacji
4. definicje TAI, UT, UTC...
5. Samoa and Tokelau skip a day for dateline
change
www.timeanddate.com
www.epochconverter.com
www.odi.ch/prog/design/datetime.php
tycho.usno.navy.mil/systime.html
www.bbc.co.uk/news/worldasia16351377
44. Dziękuję za poświęcony... czas!
Twitter:
nurkiewicz@gmail.com
@tnurkiewicz
nurkiewicz.github.io/talks/confitura2013