Wir sind ein junger Verein, der es sich zum Ziel gesetzt hat, eine starke Entwickler-Community im Raum Ingolstadt aufzubauen. Als Java-User-Group liegt unser Fokus natürlich auf der Java-Plattform mit all ihren Facetten, jedoch befassen wir uns mit der gesamten Bandbreite der Software-Entwicklung und des Betriebs.
Unser monatlicher Termin ist kostenfrei und offen für jeden.
Unsere Präsenzen im Web:
Dieser Talk ist lizensiert unter CC BY-SA 4.0.
Wer die Zeitzone nicht kennt hat schnell Weihnachten verpennt
vor einigen Java Releases…
in einer längst vergangenen Zeit…
oder etwa doch nicht?
Zeitpunkt in Millisekunden seit 1.1.1970
var date = new Date(System.currentTimeMillis());
date.toString(); // Tue Dec 03 22:08:57 CET 2019
// uses -Duser.timezone
date.setTime(1231211251L); // Mutable!
// + round about 350 @Deprecated Methods
🤮
Ortsgebundene Zeit, über java.util.Date gestülpt
var cal = Calendar.getInstance(TimeZone.getDefault());
/* Interface that uses many -Duser.* properties for
* selecting an implementation out of e.g.:
* GregorianCalendar,
* BuddhistCalendar or
* JapaneseImperialCalendar */
cal.toString();
// java.util.GregorianCalendar[time=1575409375587,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=49,WEEK_OF_MONTH=1,DAY_OF_MONTH=3,DAY_OF_YEAR=337,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=10,HOUR_OF_DAY=22,MINUTE=42,SECOND=55,MILLISECOND=587,ZONE_OFFSET=3600000,DST_OFFSET=0]
cal.set(2019, 10, 12, 18, 30, 0); // Yeah!
cal.setTimeInMillis(1231211251L); // What?
🤮🤮
Formatieren und parsen von java.util Zeiten
var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
sdf.setTimeZone(TimeZone.getTimeZone("CET"));
Date toFormat = Calendar.getInstance().getTime();
String text = sdf.format(toFormat);
// 2019-12-03T22:50:42.562+01:00
Date parsed = sdf.parse(text);
var cal = Calendar.getInstance();
cal.setTime(parsed);
🤮🤮🤮
Ohne (viele) Worte…
var today = new Date();
var tomorrow = new Date(today.getTime() + 1000 * 60 * 60 * 24);
var now = Calendar.getInstance();
now.add(Calendar.DAY_OF_WEEK_IN_MONTH, 1); // What?
now.add(Calendar.HOUR, -2); // All right
now.add(Calendar.HOUR_OF_DAY, 3); // ehhh?
// BUT: now isn't now anymore!
var sometime = (Calendar) now.clone();
// ...
🤮🤮🤮🤮🤮🤮🤮🤮🤮🤮🤮🤮
Gibt’s zum Download im Internet: https://www.iana.org/time-zones
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Germany 1947 only - Apr 6 3:00s 1:00 S
Rule Germany 1947 only - May 11 2:00s 2:00 M
Rule Germany 1947 only - Jun 29 3:00 1:00 S
Rule Germany 1948 only - Apr 18 2:00s 1:00 S
Rule Germany 1949 only - Apr 10 2:00s 1:00 S
Rule SovietZone 1945 only - May 24 2:00 2:00 M # Midsummer
Rule SovietZone 1945 only - Sep 24 3:00 1:00 S
Rule SovietZone 1945 only - Nov 18 2:00s 0 -
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
1:00 C-Eur CE%sT 1945 May 24 2:00
1:00 SovietZone CE%sT 1946
1:00 Germany CE%sT 1980
1:00 EU CE%sT
# Büsingen <http://www.buesingen.de>, surrounded by the Swiss canton
# Schaffhausen, did not start observing DST in 1980 as the rest of DE
# (West Germany at that time) and DD (East Germany at that time) did.
# DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
# which in turn is covered by the zone Europe/Berlin.
#
# Source for the time in Büsingen 1980:
# http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
Link Europe/Zurich Europe/Busingen
In der JRE enthalten:
$JAVA_HOME/lib/tzdb.dat
$JAVA_HOME/lib/tzmappings
System Umgebung (System.getProperties())
user.variant:
user.timezone:
user.country: DE
user.language: de
Benutzer Eigenschaften (System.getenv())
TZ: Europe/Berlin
LANG: de_DE.UTF-8
aber Rettung naht…
var localDate = LocalDate.now();
localDate.toString(); // 2019-12-04
Ein Tag. Irgendwo. Irgendwann.
var localTime = LocalTime.now();
localTime.toString(); // 20:47:16.232363100
Ortszeit. Zeitanzeige der Uhr.
var localDateTime = LocalDateTime.now();
localDateTime.toString();
// 2019-12-04T20:47:16.231363900
Datum und Zeit zusammen.
var offsetTime = OffsetTime.now();
offsetTime.toString();
// 20:47:16.234362400+01:00
Ortszeit inklusive Stundenversatz von Greenwich.
var offsetDateTime = OffsetDateTime.now();
offsetDateTime.toString();
// 2019-12-04T20:47:16.233362900+01:00
VersatzDatumZeit.
var zonedDateTime = ZonedDateTime.now();
zonedDateTime.toString();
// 2019-12-04T20:47:16.236364500+01:00[Europe/Berlin]
Volles Programm, Datum und Zeit, Offset und Zeitzone.
var instant = Instant.now();
instant.toString();
// 2019-12-04T19:47:16.090017700Z
Internetzeit. UTC. GMT.
Standards
TemporalAccessor ta = Instant.now();
var text = DateTimeFormatter.ISO_INSTANT.format(ta);
// 2019-12-05T20:28:37.257047300Z
ta = DateTimeFormatter.ISO_INSTANT.parse(text);
// DateTimeFormatter.BASIC_ISO_DATE
// DateTimeFormatter.ISO_WEEK_DATE
// DateTimeFormatter.RFC_1123_DATE_TIME
// import static java.time.temporal.ChronoField.*;
var dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendValue(HOUR_OF_DAY, 2).appendLiteral(":")
.appendValue(MINUTE_OF_HOUR, 2)
.appendLiteral(" Uhr am ")
.appendValue(DAY_OF_MONTH, 2).appendLiteral('.')
.appendValue(MONTH_OF_YEAR, 2).appendLiteral('.')
.appendValue(YEAR, 4).toFormatter();
dtf.format(LocalDateTime.now());
// 22:05 Uhr am 05.12.2019
dtf.parse("18:30 uhr am 10.12.2019");
Jackson
new ObjectMapper()
.registerModule(new JavaTimeModule());
Gson
new GsonBuilder()
.registerTypeAdapterFactory(
new GsonJava8TypeAdapterFactory()
).create()
Grundrechenarten
var now = LocalDateTime.now();
var nextWeek = now.plusDays(7); // Immutable
var yesterday = now.minusHours(24);
var duration = Duration.ofDays(5).plus(Duration.ofHours(2));
var sometimes = Instant.now().plus(duration);
sometimes.isAfter(Instant.now());
Duration.between(Instant.now(), sometimes);
// PT121H59M59.9990012S
Period.between(LocalDate.now(), LocalDate.of(2019, 12, 24));
// P19D
var sixMonth = Period.ofMonths(6);
var odtNow = OffsetDateTime.now();
// 2019-12-06T20:39:54.717348800+01:00
odtNow.plus(sixMonth).toString();
// 2020-06-06T20:39:54.717348800+01:00
💩
var sixMonth = Period.ofMonths(6);
var zdt = ZonedDateTime.now();
zdt.toOffsetDateTime().toString();
// 2019-12-06T20:50:36.461772200+01:00
zdt.plus(sixMonth).toOffsetDateTime();
// 2020-06-06T20:50:36.461772200+02:00
📅
var instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/Berlin"));
LocalDateTime ldt = zdt.toLocalDateTime();
OffsetDateTime odt = ldt.atOffset(ZoneOffset.ofHours(4));
zdt = odt.atZoneSameInstant(ZoneId.systemDefault());
zdt = odt.atZoneSimilarLocal(ZoneId.systemDefault());
zdt.toInstant();
🧮
Konstanter Ort: Local[Date]Time
Ortsübergreifende Zeitpunktbetrachtung (API):
Instant
Offset[Date]Time
ZonedDateTime
Speichern / Rechnen:
Instant
ZonedDateTime