Java Ist System.currentTimeMillis() systemzeitzonenabhängig?

CyborgBeta schrieb:
Das ist eine andere Use-Case-Ebene.

Es ist jedenfalls ein 0815-Usecase für eine Date/Time API.
Zitat von dir von oben, habe den relevanten Teil mal fett markiert:

CyborgBeta schrieb:
Nein, ja eben nicht (zumindest dieser Punkt). Die neue Time-Api ist viel länger und umständlicher zu schreiben (egal bei welchem Use-Case) => un-intuitiv.

Die 4 gezeigten Zeilen braucht man mit den alten APIs alleine, um eine Calendar-Instanz zu erzeugen und auf den 14. Juni zu setzen. Es sei denn, man verwendet Calendar.Builder und quetscht alles in eine lange Zeile, aber das ist eher nicht der Sinn eines Builders. Von der Datums-Arithmetik, die da nach kommt, haben wir dann noch nicht mal gesprochen. Und nichts davon ist Thread-safe. Und so weiter, und so fort.

H4110 schrieb:
Will ich sehen, aber ohne ThreeTen-Extra. 😉
:confused_alt:

Code:
ZoneId zoneId = ZoneId.of("Europe/Berlin");
ZonedDateTime start = ZonedDateTime.of(2024, 3, 30, 21, 0, 0, 0, zoneId);
ZonedDateTime target = ZonedDateTime.of(2024, 6, 14, 21, 0, 0, 0, zoneId);
Duration d = Duration.between(start, target);
System.out.println(d.toDays() + " Tage, " + d.toHoursPart() + " Stunden");

Liefert zwischen denselben lokalen Uhrzeiten, jeweils 21 Uhr, 75 Tage und 23 Stunden. Die Stunde geht heute Nacht flöten.
Verschiebe die Tage beider Datumsangaben um jeweils einen Tag nach hinten (die Zeitumstellung fällt somit nicht ins Gewicht) und es sind 76 Tage und 0 Stunden.

Wenn man in der Ausgabe aus kosmetischen Gründen lieber ganze Tage und 0 Stunden zwischen verschiedenen Datumsangaben mit gleichen Uhrzeiten hätte (Zeitumstellung hin oder her), müsste man als Zwischenschritt die vollen Tage berechnen und dann noch das Delta zum Zieldatum als Stunden. Das wären dann vielleicht nochmal 2 Zeilen dazu, auch kein Aufwand.
 
Zuletzt bearbeitet:
CyborgBeta schrieb:
Noch mal zurück zum Countdown. Ich möchte in meinem Programm keine Zeitspannen berechnen. Insofern kann mir so etwas wie die https://en.wikipedia.org/wiki/Central_European_Summer_Time auch egal sein.
Sondern was...? Du speicherst in der Datenbank Timestamps, das sind genau definierte Zeitpunkte. Die insbesondere dazu geeignet sind um Differenzen bzw. Zeitspannen zu berechnen. Die entsprechende Klasse für einen Timestamp ist java.time.Instant.

Nutze die java.time Klasse die deinem Anwendungsfall entspricht. Ich empfehle dazu diesen Stackoverflow Post: https://stackoverflow.com/questions...n-instant-and-localdatetime/32443004#32443004 (auch runterscrollen)

Die alten Date/Time/Calendar Klassen sind völliger murks und scheinen nur "simpel" weil sie die korrekte Behandlung von Zeitzonen (oder das Weglassen dieser) einfach unter den Tisch fallen lassen. Am Ende weiß man gar nicht wann wo welche Zeitzone gilt. Genau darum ist ja auch dein Thread hier entstanden.

Java ist bereits extrem konservativ unter den Programmiersprache, die java.time API wurde nach dem Design der Joda Time Library entwickelt, und das erst nachdem sich Joda Time fast ein Jahrzehnt lang bewährt hatte. (Joda Time 1.0 Release in 2005, java.time in Java 8 in 2014)
 
crvn075 schrieb:
Wenn man in der Ausgabe aus kosmetischen Gründen lieber ganze Tage und 0 Stunden zwischen verschiedenen Datumsangaben mit gleichen Uhrzeiten hätte (Zeitumstellung hin oder her), müsste man als Zwischenschritt die vollen Tage berechnen und dann noch das Delta zum Zieldatum als Stunden. Das wären dann vielleicht nochmal 2 Zeilen dazu, auch kein Aufwand.
Genau darauf wollte ich anspielen, denn einen Countdown zur EM würde ich so implementieren, also ganze Kalendertage plus Stunden. Und weil Du Period, Duration und "fast schon geschummelt" sagtest, wollte ich sehen, denn keine der beiden Klassen liefert mit einem fast schon geschummelten .between(...) die Tage und Stunden auf diese Art.

Ich dachte, PeriodDuration von ThreeTen-Extra würde das liefern, aber so wie es aussieht (habe es nicht ausprobiert), würde es für 30.3.24, 22 Uhr bis 14.6.24, 21 Uhr als Ergebnis 76 Tage und -1 Stunden liefern, was eher suboptimal ist.

WolframAlpha (fiel mir dabei irgendwie ein) liefert übrigens 2 Monate, 14 Tage und 23 Stunden:
https://www.wolframalpha.com/input?i=Duration+between+2024-03-30+22:00+CET+and+2024-06-14+21:00+CEST
 
crvn075 schrieb:
Es ist jedenfalls ein 0815-Usecase für eine Date/Time API.

Nein, das ist yagni für mich, weil ich es nicht brauche (und vermutlich auch nicht brauchen werde). Ich muss nur einen timestamp speichern, und diesen timestamp in einer lokalen Zeitzone interpretieren können. Und dafür kann ich auch die "alte" api nutzen.

crvn075 schrieb:
Von der Datums-Arithmetik, die da nach kommt, haben wir dann noch nicht mal gesprochen. Und nichts davon ist Thread-safe. Und so weiter, und so fort.

Noch mal, ich brauche die Datums-Arithmetik nicht. Aber auch das wäre relativ simpel, wenn man von unserer Zeitzone und der Zukunft ausgeht.

Code:
c = b-a (c wäre die Zeitdifferenz der zwei timestamps a und b)
s_a = is_summertime(a)
s_b = is_summertime(b)
wenn !s_a und s_b :
  c -= 1 Stunde
wenn s_a und !s_b :
  c += 1 Stunde

Zeitdifferenz in Tage, Stunden, Minuten, Sekunden umrechnen und ausgeben.

Wo liegt nun das Problem?

Frohe Ostern, btw.
 
Guten Morgen,

ich wünsche allen Thread-Teilnehmern eine frohe Sommerzeit. Wer die Stunde, die der Osterhase versteckt hat, findet, darf zur Belohnung in das Rabbit Hole der Best Practices, angefangen bei der Speicherung von Timestamps (with time zone?) in Datenbanken bis hin zu der lokalisierten Darstellung im Frontend, hinabsteigen. 👯 🤪
 
  • Gefällt mir
Reaktionen: CyborgBeta
Zwei Kleinigkeiten wollte ich hier noch in die Runde werfen: der Overhead bei der Erzeugung von Date's der alten API ist gewaltig.

SimpleDateFormat ist nicht threadsafe, muss als jedes Mal neu erstellt oder per Thread Local gehalten werden.

DateTimeFormat hingegen ist threadsafe, wie auch die restliche java.time API. Allein deshalb sollte man die alte API schnell vergessen.

Zu guter Letzt an den Threadersteller: Meinst du statt "Streams" eher die Fluent-artige Schreibweise und hast dich nur unglücklich ausgedrückt?
 
codengine schrieb:
Zu guter Letzt an den Threadersteller: Meinst du statt "Streams" eher die Fluent-artige Schreibweise und hast dich nur unglücklich ausgedrückt?

Ja. Aber ich weiß, worauf du hinaus möchtest. 1. Thread-Sicherheit brauchen die meisten Anwendungen nicht, und 2. ist die "neue" API auch nicht wirklich fluent designend worden. ... Wie gesagt, ich warte noch auf etwas "Drittes". ;) Alsweilen nutze ich die "alte" api.
 
Mir fällt gerade noch auf, dass wir eigentlich Äpfel mit Birnen verglichen haben.

Altes und neues API haben jeweils eine Klasse, die einen konkreten Zeitpunkt repräsentiert:
Date und Instant - jeweils ohne Zeitzone. Alles, was bei Date darüber hinaus geht, ist seit Java 1.1 deprecated.

Wenn man die formatieren will, muss der Formatter eine Zeitzone haben.

Java:
public class FormatInstant {
 public static String oldSchool(long epochMillis) {
  var f=SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.MEDIUM, SimpleDateFormat.MEDIUM);
  f.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
  var d=new Date(epochMillis);
  return f.format(d);
 }


 public static String newSchool(long epochMillis) {
  var f=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.of("Europe/Berlin"));
  var d=Instant.ofEpochMilli(epochMillis);
  return f.format(d);
 }
}

Für Datum/Zeit mit Zeitzone haben altes und neues API Calendar bzw. GregorianCalendar respektive ZonedDateTime, welche die Zeitzone mitbringen:

Java:
public class FormatDateTime {
 public static String oldSchool(long epochMillis) {
  var f=SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.MEDIUM, SimpleDateFormat.MEDIUM);
  var d=new Calendar.Builder().setInstant(epochMillis).setTimeZone(TimeZone.getTimeZone("Europe/Berlin")).build();
  return f.format(d.getTime());
 }


 public static String newSchool(long epochMillis) {
  var f=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
  var d=Instant.ofEpochMilli(epochMillis).atZone(ZoneId.of("Europe/Berlin"));
  return f.format(d);
 }
}

Ich finde, in beiden Fällen ist das neue API eindeutig eleganter und auch etwas prägnanter.
Ergänzung ()

Wenn man ein Instant mit einem Formatter ohne Zeitzone formatiert, fliegt übrigens eine Exception. Kann man drüber streiten, ob das gut oder schlecht ist, aber man bemerkt zumindest den Fehler. Date wird einfach stillschweigend in UTC formatiert.

Und was genau macht eigentlich Calendar#setTimezone? Das neue API ist da mit withZoneSameInstant und withZoneSameLocal eindeutiger.

Ich sehe nur Vorteile.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Marco01_809 und CyborgBeta
H4110 schrieb:
Ich sehe nur Vorteile.

Ich nicht. Aber das bleibt eine Sache des Geschmacks, ähnlich wie die Frage nach der besten Religionsform, etc.
 
Es ist eben keine Frage des Geschmacks. Wäre die alte API so toll gäbe es keine Notwendigkeit für sowas wie JodaTime, und der Autor davon schreibt selber dass

"Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project"

Der einzige Grund den ich sehe warum es die alte API noch gibt ist aus Abwärtskompatibilitätsgründen, und man sollte sich nicht an alten gammeligen Zöpfen festhalten sondern sie abschneiden :D
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Marco01_809
Ach? Keine Frage des Geschmacks? Wirklich? Dann kannst du doch sicher ein paar objektive Gründe für die neue API nennen, oder?

Ergänzung ()

Btw., das "Neue", der "Heilige Gral", die "Dritte" API (oder zumindest eine Erweiterung der vorherigen), die die Nachteile von java.time. verbessern wird (die es ja angeblich laut euch gar nicht gibt ...), ist schon "da" bzw. an ihr wird gerade entwickelt: ThreeTen-Extra ...

Siehe auch:

https://www.threeten.org/threeten-extra/ und https://stackoverflow.com/a/42498249

Damit ist für mich dieses Thema dann auch gegessen.
Ergänzung ()

Not every piece of date/time logic is destined for the JDK. Some concepts are too specialized or too bulky to make it in. This project provides some of those additional classes as a well-tested and reliable jar. It is curated by the primary author of the Java 8 date and time library, Stephen Colebourne.

Nicht jeder Teil der Datums-/Zeitlogik ist für das JDK bestimmt. Einige Konzepte sind zu spezialisiert oder zu sperrig, um dort aufgenommen zu werden. Dieses Projekt stellt einige dieser zusätzlichen Klassen in Form eines gut getesteten und zuverlässigen Jars zur Verfügung. Es wurde vom Hauptautor der Java 8 Datums- und Zeitbibliothek, Stephen Colebourne, kuratiert.
 
Zuletzt bearbeitet: (war zu provokativ ...)
CyborgBeta schrieb:
Dann kannst du doch sicher ein paar objektive Gründe für die neue API nennen, oder?

Immutability, kostet weniger Speicher, Zeitzone wird mitgeführt, klare Unterscheidung zwischen LocalDate(Time), ZonedDate(Time) und Instant (äquivalent zum jetzigen Date).

Gerade der Punkt mit der fehlenden Zeitzone ist eine beliebte Quelle für Fehler, insbesondere in großen Projekten.
Ergänzung ()

CyborgBeta schrieb:
die es ja angeblich laut euch gar nicht gibt
Das hat keiner behauptet.
Ergänzung ()

CyborgBeta schrieb:
Lustig dass du gerade das verlinkst. Da steht:

Avoid these legacy classes entirely. Use java.time classes instead.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Marco01_809
ThreeTen ist kein Ersatz für java.time, sondern erweitert java.time um weitere Klassen/Teil-Daten/Kalendersysteme. Damit wird java.time als API der Wahl weiter gefestigt. Weil java.time eben so vorausschauend und durchdacht designed wurde das es wahrscheinlich der letzte Teil des JDKs ist der jemals ersetzt werden muss.

Irgendwo nervt es mich persönlich ja schon. Früher oder später gerät man an irgendeine Verwaltungssoftware, -website o.Ä. die man gezwungen ist zu nutzen, wo dann genau solcher Pfuscher-Code drin gelandet ist mit Zeitumstellungs-Problemen die man schon vor 10 Jahren endgültig behoben hat. Reflexartig rollen die Augen zurück und man überschlägt wie viele Tausende Stunden Lebenszeit von Nutzern dieser Müllhaufen schon gekostet hat. Nur weil so eine Schamane die 30 Minuten nicht investieren wollte um die 10 Jahre alte API richtig zu verstehen und anzuwenden während die ganze Welt ihn anschrie: "NIMM JAVA.TIME!!!"
 
Marco01_809 schrieb:
Welt ihn anschrie: "NIMM JAVA.TIME!!!"

Ich setze doch heute nix ein, was in einem Jahr ohnehin wieder obsolet sein wird, und nochmals ersetzt werden muss. 🤡

Zum Teil ist dies aber auch der sich ändernden Wirklichkeit geschuldet, siehe dazu noch mal #20 bzw.:


tl;dr: Zeitzonen sind (genau wie Ländergrenzen) keine auf Ewigkeit in Stein gemeißelte Konstrukte, sondern sind gewissermaßen dynamisch und abhängig von sich ändernden Umweltbedingungen... (es sei denn natürlich, sie wurden von der NATO festgelegt, dann sind sie unveränderbar ;))
 
Ganz richtig, Zeitzonen ändern sich ständig. Tlw. ist es sogar vom Datum abhängig wie das Datum zu interpretieren ist, weil die neue Zeitzonen-Definition erst ab Stichtag X gilt! Alle diese Informationen und Regeln werden in der tz database gepflegt. Diese ist z.B. in deinem Betriebssystem und auch im JDK enthalten und wird mit regelmäßigen Updates immer aktualisiert.

Darum darf man in seinen Programmen auch keine Annahmen über Zeitzonen treffen sondern muss alle Operationen über eine sauber abstrahierte Bibliothek vornehmen, die im Hintergrund alle tz Regeln für dich anwendet, wie z.B. java.time.
 
  • Gefällt mir
Reaktionen: CyborgBeta
CyborgBeta schrieb:
Ich setze doch heute nix ein, was in einem Jahr ohnehin wieder obsolet sein wird, und nochmals ersetzt werden muss. 🤡
Java 8 (samt java.time) kam vor 10 Jahren raus, wieso sollte sich was ändern? Es ist ja noch nicht mal ein Nachfolger angekündigt worden.
 
  • Gefällt mir
Reaktionen: CyborgBeta
CyborgBeta schrieb:
Ich nicht. Aber das bleibt eine Sache des Geschmacks, ähnlich wie die Frage nach der besten Religionsform, etc.
Mal ganz ehrlich. Bei diesem Thema gibts in meinem beruflichen Umfeld keinerlei Unstimmigkeiten. Es herrscht ein Konsens dass die alte java.util.Date API viele Schwachstellen hat und nicht mehr verwendet werden soll. Deine Meinung dass die neue API kontraintuitiv wäre kann ich ebenfalls nicht nachvollziehen.

Hier mal ein Beispiel aus der alten API:
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
In der neuen java.time:
The month-of-year to set in the returned year-month, from 1 (January) to 12 (December)

Ansonsten gib es genug ausführlich Artikel über die Designmängeln der alten Java API: ALL ABOUT JAVA.UTIL.DATE

Wenn du dennoch meinst schlauer zu sein als 99% der restlichen JVM Community dann nutz gerne weiter java.util.Date.:D

Marco01_809 schrieb:
ThreeTen ist kein Ersatz für java.time, sondern erweitert java.time um weitere Klassen/Teil-Daten/Kalendersysteme.
Das ist falsch. ThreeTen war ein Projekt im Java Community Process Program welches als Reference Implementation des JSR-310 (Java Specification Requests) diente. Dieses wurde dann als java.time in Java 8 integriert. Siehe JCP Program and Industry Awards und SourceForge wiki
ThreeTen provides a modern date and time library for Java and is the reference implementation for JSR-310. It includes many of the lessons of the Joda-Time project and aims to standardise date and time concepts in computing. Code now integrated into OpenJDK, this project is archived.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: CyborgBeta und sh.
G00fY schrieb:
Das ist falsch. ThreeTen war ein Projekt im Java Community Process Program welches als Reference Implementation des JSR-310 (Java Specification Requests) diente. Dieses wurde dann als java.time in Java 8 integriert. Siehe JCP Program and Industry Awards und SourceForge wiki
Wieder was gelernt, ich dachte immer JodaTime wäre die Referenz-Implementierung :D
Aber klar so herum macht es viel mehr Sinn.
 
  • Gefällt mir
Reaktionen: CyborgBeta und G00fY
codengine schrieb:
Wieder was gelernt, ich dachte immer JodaTime wäre die Referenz-Implementierung :D
JodaTime ist vom selben Author der später den JSR-310 in Form von ThreeTen implementiert hat:
Over the years, I have produced two libraries for Java date and time.

The first is Joda-Time, a library has become the de facto standard choice for many users.

The second is JSR-310, included as java.time in Java SE 8.
ThreeTen-Backport vs Joda-Time
 
G00fY schrieb:
Das ist falsch. ThreeTen war ein Projekt im Java Community Process Program welches als Reference Implementation des JSR-310 (Java Specification Requests) diente.
Stimmt, ich habe das mit dem verlinkten ThreeTen-Extra verwechselt. ThreeTen-Extra erweitert aber in der Tat java.time um zusätzliche Funktionen und erbt/implementiert direkt von java.time.* Klassen/Interfaces.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Zurück
Oben