Warum gibt es keinen echten "Nur-Datum" -Datentyp?

24

Ich bin so lächerlich frustriert, DateTime-Werte für Datensätze verwenden zu müssen, die wirklich "nur ein Tag" sind. Geburtstage sind das häufigste Beispiel, aber dies kommt in Geschäftsanwendungen immer wieder vor.

Ich habe mich daran gewöhnt, den Zeitteil von "Nur-Datum" -Datensätzen auf "Mittag" zu setzen (wodurch vermieden wird, dass sich das Datum unabhängig von der Zeitzone ändert). Dies scheint ein Hack zu sein, und ich finde immer wieder Bugs von Junior-Entwicklern, die sich mit diesem Problem befassen.

Die Zeit ist immer relativ zu einem festen Punkt. 16 Uhr ist 4 Stunden nach dem Meridian oder Mittag. Der höchste Transitpunkt der Sonne ist beobachtbar und ermöglicht die Einrichtung eines Koordinatensystems. 3 Stunden vor Mittag (Ante Meridian), 2 Stunden nach Mittag, 1441899402938 Millisekunden seit dem 1. Januar 1970. Für Menschen, die in einer kartesischen Welt aufwachsen, ist dies eine zweite Natur.

Unser Kalender ist jedoch älter als Descartes. Mein Argument ist, dass es eher als eine Aufzählung aufgefasst wird, auf die eine Modulo-Funktion angewendet wird. Montag folgt auf Sonntag und so weiter, bis Sie feststellen, dass Sonntag auf Samstag folgt. Es gibt kein positives und negatives, es ist ein Modul oder ein absoluter Wert.

Ähnlich mit Jahren zu wiederholen. Alle 365 Tage (oder so) gibt es einige besondere Tage für mich: Geburtstage, Jahrestage, Kindergeburtstage usw. usw. In den Anwendungen für die Geschäftsplanung gibt es viele Beispiele für Besprechungen alle sieben Tage, am ersten Dienstag im Monat usw. Nur weil wir KÖNNEN dies auf eine Gleitkommazahl abbilden, und in Wahrheit löst das Abbilden auf diese Zahl VIELE Probleme, die auf die alte Weise wirklich schwierig sind, aber das bedeutet nicht, dass es die einzige Möglichkeit ist, dies zu tun.

Meiner Meinung nach sind Sie ein besserer Programmierer, wenn Sie wissen, wie DateTimes zum Speichern von Datumsangaben verwendet wird.

Gibt es in einer Anwendung einen Wert, der ausdrücklich als Planungsanwendung für die Definition einer Datumsklasse gedacht ist, oder ist "Alle Zeiten auf Mittag setzen" der beste Ansatz? Welche Probleme können bei der Verwendung von DateTime und dem Festlegen der Zeitkomponente auf Noon auftreten? Kann die Zeitverschiebung in einem solchen Ansatz berücksichtigt werden? Ich habe MomentJS verwendet, aber ich denke, das ist nur eine bessere Date-Klasse.

Michael Blackburn
quelle
7
Das ist eine ziemlich interessante Frage, denke ich. Nehmen wir das Geburtstags-Beispiel, es macht nur beim Menschen wirklich Sinn, ich lebe an einem Ort und jeder wacht zur selben Zeit auf eine Art und Weise auf. Sobald Sie es mathematisch ausdrücken müssen, wird es sehr komplex. Das Gleiche gilt für Sachen wie Arbeitsschicht Start- / Endzeiten etc sie Arent ‚mal‘ sie ‚Stunden des Tages in der Zeitzone , in der Sie arbeiten‘ sind
Ewan
3
NodaTime (eine C # -Bibliothek für Datum und Uhrzeit) hat einen Datentyp.
CodesInChaos
5
Speichern Sie Ihre Zeiten in UTC, ohne Datums- oder Zeitzonenprobleme.
Loren Pechtel
3
"Aber Gott, das scheint ein Hack zu sein, und ich finde immer wieder Bugs von Junior-Entwicklern, die sich mit diesem Thema befassen." - Warum erstellen Sie nicht einfach Ihre eigene DateOnly-Klasse oder was auch immer und nennen es einen Tag?
Brandin
5
@ MichaelBlackburn Ich meine es ernst. Ihre Erklärung klingt genau nach der Situation für einen eigenen Datentyp, der die Geschäftsregel erzwingt (nur Datum, z. B. können Sie es als "DateTime" intern mit dem auf Mittag eingestellten Zeitteil speichern), aber dann nur die gewünschten Teile verfügbar machen (Monat) , Tag usw. Jahr / kein Jahr).
Brandin

Antworten:

15

Lassen Sie uns zunächst eines aus dem Weg räumen: Geburtstage sind eine Sache, Geburtsdaten eine andere. Ein Geburtstag ist ein exotischer Datentyp, da ihm nicht nur die Komponenten Stunden, Minuten usw. fehlen, sondern auch die Jahreskomponente. Wenn Sie sich wirklich mit Geburtstagen befassen möchten, würde ich empfehlen, einen eigenen Datentyp zu erfinden, der nur eine Monats- und eine Tageszahl enthält und mit keinem der integrierten Datentypen für Datum und Uhrzeit zusammenhängt.

Wenn Sie andererseits auch das Geburtsjahr im Auge behalten möchten, dann sind es nicht die Geburtstage, sondern die Geburtsdaten . Nun stellt sich die Frage, warum es keinen Datentyp nur für das Datum gibt, sodass Sie Geburtsdaten bequem darstellen können, und stattdessen scheinen gängige Sprachen Sie zu zwingen, einen Typ zu verwenden, der auch eine Zeitkomponente enthält.

Lassen Sie mich kurz erwähnen, dass es nicht stimmt, dass alle Programmiersprachen nur temporäre Datentypen anbieten, die eine Zeitkomponente enthalten. Ich bin auf Datentypen gestoßen, die nur für Datumsangaben bestimmt sind, und auf Datentypen in den entsprechenden SQL-Dialekten. Das ist jedoch unerheblich: Die Tatsache, dass diese Datentypen existieren, bedeutet nicht, dass sie eine gute Sache sind, und RDBMSs haben eine lange Tradition darin, Speicher mit Repräsentation zu verwechseln.

Sie werden verstehen, warum es eine schlechte Idee ist, solche Nur-Datum-Datentypen zu verwenden, sobald Sie erkennen, dass die Zeit eine Koordinate ist. Die meisten Menschen haben eine sehr vage Vorstellung davon, was Zeit ist, und diese Vorstellung enthält arkane kulturelle Begriffe wie Jahre, Monate und Tage, ohne zu begreifen, dass diese Begriffe ausschließlich repräsentativ sind : Sie sind nur nützlich, um Zeit für einen Menschen darzustellen und zu empfangen Zeit als Eingabe von einem Menschen. Auf jeder Ebene unterhalb der GUI-Steuerung für die tatsächliche Zeiteingabe sollte und wird die Zeit in der Regel als Zeitkoordinate dargestellt, die eine einzelne Anzahl von Zeiteinheiten seit einem bestimmten Ursprung darstellt.

Im DateTimeDatentyp von Microsoft Dotnet beträgt die Zeiteinheit beispielsweise 100 Nanosekunden, und der Ursprung der Zeit ist der 1. Januar 0001 (Mitternacht)

Ein weiteres Beispiel für eine arkane, ausschließlich gegenständliche Notation sind Winkelmessungen in Grad, Minuten und Sekunden. Um nützliche Berechnungen durchführen zu können, müssen Sie natürlich intern das Bogenmaß verwenden und gegebenenfalls bei der Interaktion mit einem menschlichen Benutzer von und zu Grad konvertieren.

Verwechseln Sie daher nicht die vom Menschen lesbare Darstellung einer Messung mit der tatsächlichen Art der Messung. Sehr oft unterscheidet sich die ideale Methode zur Durchführung einer Messung, die der Art der Messung am ehesten entspricht, stark von der vom Menschen lesbaren Darstellung dieser Messung.

In Anbetracht dessen ähnelt Ihre Anfrage nach einem temporären Datentyp, der nur Daten darstellt, einer Anfrage nach einem Winkeldatentyp, der nur Grad darstellen kann, was eine größere Genauigkeit explizit verhindert. Solch ein Datentyp wäre sehr begrenzt und letztendlich nutzlos, da man ihn sowieso in und von Radianten konvertieren müsste, um irgendetwas Nützliches damit anfangen zu können.

Ihr Problem mit dem Geburtsdatum ist, dass Sie eine ungenaue Zeitkoordinate haben: Die Person wurde natürlich zu einem bestimmten Zeitpunkt geboren, aber die Stunde und Minute wurden entweder nicht vom Krankenhaus aufgezeichnet, oder wir haben keine kümmern uns um sie. Was also wirklich passiert, ist, dass Ihre Koordinate von Geburtsdatum und -uhrzeit eine Fehlerquote, Toleranz oder Unsicherheit aufweist, wenn Sie dies wünschen, und es ist am besten, sie als solche zu behandeln: Setzen Sie sie genau in die Mitte des Tages, und betrachten Sie eine implizite +12 -12 Stundenunsicherheit. Und genau zu dieser Lösung sind Sie intuitiv gekommen.

Mike Nakis
quelle
4
Dies gilt nicht für "Tage", die ein Konzept sind, das noch älter als die Zeit ist. Sie werden am ehesten als Aufzählung oder als Modul angesehen. Der Sonntag folgt auf den Montag usw., bis wir auf den Sonntag zurückkommen, der auf den Samstag folgt. Es ist wirklich eine andere Sache.
Michael Blackburn
10
Nun natürlich schrieb das Krankenhaus , um die Zeit der Geburt nach unten - , die in den meisten Krankenhäusern üblich ist. Darum geht es überhaupt nicht. Das Problem ist, dass zum Gedenken an Ereignisse (Geburtstage, Feiertage, Jahrestage usw.) keine Auflösung verwendet oder gewünscht wird, die feiner als 1 Tag ist. Fragen Sie die erste Person, die Sie sehen, wann sie Geburtstag hat, und sie gibt Ihnen einen Monat und einen Tag, aber niemals eine Stunde und eine Minute. Außerdem verwenden wir Einheiten, die ständig skaliert werden: Millimeter, Kilogramm, Megawatt und in der Tat Mikrofarad.
Caleb
4
-1: Nicht alle Zeitverwendungen sollen einen einzelnen Moment in der Zeit darstellen. Ein Geburtstag ist eine andere Idee, dargestellt durch einen Monat und einen Tag im Gregorianischen Kalender. Es ist sinnvoll zu fragen, ob Kevin heute Geburtstag hat. Die Antwort ist ortsabhängig. Wenn ich in Sydney bin, könnte es mein Geburtstag sein, aber wenn ich stattdessen in Honolulu wäre, würde es noch einige Stunden dauern.
Kevin Cline
6
@ MikeNakis Das Ergebnis wäre Mikroampere, kein Unsinn. Wichtiger: Wenn Sie ein Datum anstelle einer Sekunde oder Millisekunde verwenden, sprechen Sie im Allgemeinen über den gesamten Tag - einen Zeitraum - und nicht über eine bestimmte Zeit, und je nach Kontext kann es sich um ein sich wiederholendes Ereignis handeln.
Caleb
4
Das OP sprach von Geburtstagen, die genau durch java.util.MonthDay dargestellt werden. Ein Geburtstag ist kein Maß, es ist die menschliche Vorstellung von einem Tag, der sich jährlich wiederholt. Es gibt viele menschliche Zeitvorstellungen, die nicht durch einen einzigen Zeitpunkt repräsentiert werden.
Kevin Cline
9

Daten und Zeiten sind je nach Kontext sehr unterschiedlich, und Sie benötigen viele separate Typen, um alle Anwendungsfälle abzudecken.

Der DateTimein vielen Sprachen vorhandene Typ repräsentiert einen genauen Zeitpunkt ("Momentanzeit"). Darüber hinaus gibt es eine Reihe relativer oder "menschlicher" Zeit- und Zeitbereichskonzepte wie Kalendertage, wiederkehrende Daten, Monate, Jahre usw., die in vielen Fällen mehrdeutig und kontextabhängig sind. Diese Typen sind nicht so universell verwendbar, aber in bestimmten Anwendungsbereichen wie Kalendern, Planungswerkzeugen und anderen Anwendungen, die mit menschlichen Zeitkonzepten interagieren, erforderlich.

Wenn Sie so etwas wie eine Kalender-App schreiben, profitieren Sie auf jeden Fall von einer Bibliothek wie Joda-time, die eine größere Anzahl von Zeittypen bietet. Zum Beispiel LocalDateein Datum ohne Uhrzeit. Dies hat eine andere Semantik als eine gewöhnliche, DateTimebei der der Zeitteil auf Null gesetzt ist, da der DateTimeimmer noch einen bestimmten Zeitpunkt (Mitternacht in einer bestimmten Zeitzone) LocalDateangibt , während der ganze Tag angibt und nicht an eine bestimmte Zeitzone gebunden ist. Dies bedeutet auch, dass Sie nicht direkt in das andere übersetzen können.

LocalDateist sicherlich einfacher, als DateTimeweil es keine Zeitzonen berücksichtigen muss, aber Sie sollten sich der anderen Probleme bewusst sein, z. B. dass das aktuelle Datum beim Überqueren einer Zeitzone möglicherweise tatsächlich zurückgeht und derselbe Zeitpunkt entsprechen verschiedenen Daten in verschiedenen Zeitzonen. Wenn Sie lokale Daten in Netzwerk- oder Web-Apps verwenden, sollten Sie diese Probleme mit äußerster Vorsicht behandeln. Das Entfernen des Zeitteils von einem Datum löst nicht das grundlegende Problem der Zeitzonen! Und wenn Sie historische Daten und unterschiedliche Kulturen berücksichtigen, wird es noch schwieriger, da dasselbe Datum möglicherweise zu ganz unterschiedlichen Zeitpunkten im Julianischen oder im Gregorianischen Kalender führt.

Jetzt fragen Sie, warum Sprachen nicht so etwas wie LocalDate eingebaut haben . Zunächst einmal haben einige Sprachen wie SQL und Visual Basic einen Datumstyp ohne Zeitanteil. Und Java hat LocalDatein der aktuellen Version auch eine hinzugefügt . Andere Plattformen wie .Net tun dies jedoch nicht. Nur die Sprachdesigner können wirklich antworten, warum dies nicht in der Standardbibliothek enthalten ist. Ich würde jedoch davon ausgehen, dass "Momentanzeit" konzeptionell einfach und universell nützlich ist, während die anderen Zeitkonzepte nur für bestimmte Anwendungsbereiche (wie Kalender usw.) .). Daher ist es sinnvoll, den Anwendungsentwickler benutzerdefinierte Typen schreiben zu lassen, um die komplexeren Anwendungsfälle zu behandeln, oder sie von einer Drittanbieter-Bibliothek (wie Joda-time) behandeln zu lassen.

JacquesB
quelle
5

Ich bin so lächerlich frustriert, DateTime-Werte für Datensätze verwenden zu müssen, die wirklich "nur ein Tag" sind. Geburtstage sind das häufigste Beispiel, aber dies kommt in Geschäftsanwendungen immer wieder vor.

Dies liegt wahrscheinlich daran, dass Kalender kompliziert sind und auf so viele verschiedene Arten verwendet werden, dass niemand in der Lage war, eine Klasse zu finden, die einfach und dennoch allgemein genug ist, um in vielen Bereichen nützlich zu sein.

Der in Programmiersprachen übliche Datumstyp kann verwendet werden, um Transaktionen in einem Computersystem genau zu datieren. Andere Anwendungsfälle erfordern wahrscheinlich eine benutzerdefinierte Bibliothek.

Hier finden Sie eine kurze Auflistung von Fakten zu Kalendern, die deren Komplexität veranschaulichen. Die meisten davon sind historisch. Wenn Sie sich also auf Daten nach dem 1.1.1970 beschränken, sind Sie davon nicht betroffen. Wenn Ihre Anwendung jedoch mit Daten arbeiten muss, die vor dem späten 19. Jahrhundert liegen, sind diese Fakten von Bedeutung. Mögliche Anwendungsfälle sind historische Datenbanken aller Art (Bücher, Genealogie), aber auch Vermögenswerte großer Unternehmen oder Organisationen, die bis heute aktiv sind.

All diese Tatsachen sind von dem ausgezeichneten zitierte FAQ im Kalender Bibliothek für OCaml geschrieben von Julien Signolles gefunden.

  1. Der julianische Kalender wurde 45 v. Chr. Von Julius Cäsar eingeführt. Es war bis in die 1500er Jahre üblich, als die Länder begannen, auf den Gregorianischen Kalender umzusteigen (Abschnitt 2.2). Einige Länder (z. B. Griechenland und Russland) verwendeten es jedoch bis in die 1900er Jahre hinein, und die orthodoxe Kirche in Russland verwendet es immer noch, wie einige andere orthodoxe Kirchen.

  2. Der Wechsel vom julianischen zum gregorianischen Kalender verlief nicht einheitlich und je nach Jahr des Wechsels wurden 10 bis 13 Tage gestrichen. In Frankreich folgte dem 9. Dezember 1582 der 20. Dezember 1582 und in Griechenland dem 9. März 1924 der 23. März 1924.

  3. Selbst in der Neuzeit werden viele verschiedene Kalender verwendet (Gregorianische, orthodoxe, islamische und chinesische), um einige zu zitieren, die alle unterschiedliche Methoden zur Berechnung von Jahren und Jahrestagen oder der religiösen Feierlichkeiten verwenden.

Nun hoffen Sie auf einen Datumstyp, der mit Vorgängen gebündelt ist, die für den allgemeinen Geschäftsbetrieb nützlich sind. Ich denke, es gibt keinen allgemeinen Geschäftsbetrieb. In der Finanzwelt müssen wir beispielsweise Folgendes berechnen:

  1. Jahresbruchteile (wie „6 Monate“ entsprechen „0,5“), die in Verbindung mit einem Zinssatz verwendet werden, um die tatsächlichen Zinsen für ein Darlehen für eine bestimmte Laufzeit zu berechnen. Es gibt 6 bis 10 Rezepte zur Berechnung dieser Brüche, die sich in der Art und Weise unterscheiden, wie sie mit der Länge eines Schaltjahres, der Position des Zeitraums in Bezug auf den letzten Tag im Februar und der Dauer eines Monats umgehen.

  2. Bei der Berechnung von Jahrestagen verwenden wir einen Geschäftskalender und eine Regel (ausgewählt aus einem Satz von mehr als 6 verschiedenen Regeln), um ein Jubiläum von einem Feiertag zu einem Geschäftstag zu verschieben.

Für Leute, die in der Finanzbranche arbeiten, ist jeder Kalendertyp, der nicht alle diese Funktionen und Regeln implementiert, nutzlos. Es ist wahrscheinlich, dass viele andere Branchen andere Arten von Gewohnheiten und Konventionen haben, die benutzerdefinierte Berechnungen im Kalender erfordern.

Gibt es in einer Anwendung einen Wert, der ausdrücklich als Planungsanwendung für die Definition einer Datumsklasse gedacht ist, oder ist "Alle Zeiten auf Mittag setzen" der beste Ansatz? Welche Probleme können bei der Verwendung von DateTime und dem Festlegen der Zeitkomponente auf Noon auftreten? Kann die Zeitverschiebung in einem solchen Ansatz berücksichtigt werden? Ich habe MomentJS verwendet, aber ich denke, das ist nur eine bessere Date-Klasse.

Wenn Sie einen einzelnen Kalendertag nachverfolgen müssen, ist es wahrscheinlich am besten, eine große Ganzzahl zu verwenden, die den julianischen Tag dieses Kalendertags darstellt. Algorithmen zur Umrechnung des Julianischen Tages in den Kalendertag - beschrieben mit Jahr, Monat und Kalender - sind weithin bekannt und gründlich getestet, sodass Sie sie einfach in Ihre Anwendung implementieren können - und herausfinden können, welche Regel in Ihrer Anwendung relevant ist Fall, um den Jahrestag eines Ereignisses zu berechnen, das am 29. Februar stattgefunden hat.

Michael Le Barbier Grünewald
quelle
2

Ich denke, Mike Nakis in seiner obigen Antwort kann besser erklären, wie Zeit im Allgemeinen eine absolut gemessene Koordinate ist, und jede andere Kommunikation, angenommener Zustand oder Beharrlichkeit dieser Zeitkoordinate ist lediglich eine abstrahierte Darstellung dieser Zeitkoordinate.

Sie sprechen von solchen Darstellungen, wenn Sie den Wochentag lediglich als eine Art Moduldarstellung eines tatsächlichen Zeitpunkts bezeichnen. In Wirklichkeit ist es etwas komplizierter. Wenn Sie beauftragt wurden, eine Funktion zu schreiben, die den Wochentag für einen bestimmten Zeitpunkt zurückgibt, berücksichtigen Sie die folgenden Informationen, die Sie als Eingabe für einen solchen Algorithmus benötigen. Sie benötigen den zu berücksichtigenden Zeitpunkt, den Kalender und die Zeitzone. (Beachten Sie, dass sich die Zeitzonen STÄNDIG ändern, damit Sie wissen müssen, wann diese effektive Zeitzone begann, als sie in bestimmten Zeitkoordinaten endete. Nordkorea kürzlich nur hat zum Beispiel ihre geändert!), und wenn die Sommerzeit aktiv ist, ändert sich dies auch mit der Zeit. Überlegen Sie nun, ob Sie eine DateTime in der lokalen Zeitzone erhalten haben.

Sie können sehen, wie kompliziert diese scheinbar einfache Frage wirklich sein kann.

Ich kenne den Schmerz, den Sie verspüren, als ich zu einem bestimmten Zeitpunkt in Ihren Schuhen war, um alle Fehler in einer Besuchsplanungsanwendung für ein Produkt zu beheben, das von unerfahrenen Entwicklern geschrieben wurde. Das Ganze musste verschrottet werden.

Die Zeit ist in der Tat eine Koordinate. Berücksichtigen Sie jedoch neben dem Datum auch andere zeitkritische Daten, die möglicherweise benötigt werden:

Dauer: Ein Zeitraum von Millisekunden, der eine Zeitspanne oder einen Zeitablauf ohne Angabe bestimmter Zeitkoordinaten angibt. Ein Anwendungsfall könnte sein,

Als Benutzer möchte ich, dass diese Aufgabe 15 Sekunden nach Abschluss des Mitternachtsjobs jeden zweiten Mittwoch ausgeführt wird.

Intervall: Ein Zeitraum zwischen zwei bestimmten Zeitkoordinaten. Ein Anwendungsfall, in dem Sie ein Intervall berücksichtigen möchten.

Als Benutzer muss jeder Tag des Monats innerhalb eines bestimmten Zeitintervalls vollständig angezeigt werden.

Ein weiterer kurzer Punkt, den ich ansprechen wollte, ist, dass Sie einen Kommentar zu Gleitkommazahlen für zeitbasierte Daten abgegeben haben und ich rate davon ab. Fließkomma-Arithmetik führt zwangsläufig zu Rundungsfehlern, die Ihnen möglicherweise nicht die für die Zeit erforderliche Genauigkeit verleihen.

Zusammenfassend führen alle diese Informationen unweigerlich zu den folgenden Überlegungen zum Design:

  • Bestimmte Zeitpunkte oder Zeitbereiche sollten in UTC oder einem Datentyp beibehalten werden, der genügend Informationen enthält, um bei Bedarf problemlos wieder in UTC abstrahiert zu werden
  • Die Anwendungslogik sollte so geschrieben werden, dass UTC oder ein Bereich von UTC-Koordinaten in einen repräsentativen Datenzustand umgewandelt werden, der für den Endbenutzer besser verdaulich ist.
  • Wichtige Dauern sollten in Millisekunden beibehalten werden
  • Gebietsschemaspezifische oder Endbenutzerpräferenzen bei der Anzeige von Zeitdaten sollten als zusätzliche Daten beibehalten und wie eine Anzeigeoption behandelt werden. (Z. B. Kiosk A, zentrale Zeitzone, militärisches Zeitformat oder Benutzereinstellungen B, Standardzeit in der Zeitzone von Tel Aviv (GMT + 7: 00) usw.)
  • Vermeiden Sie FP-Nummern
maple_shaft
quelle
1
Nichts davon ist "unvermeidlich". Es mag für viele Anwendungen üblich sein, aber der Large Hadron Collider befasst sich mit Ereignissen im Nanosekundenbereich. Die Systemzeiten wurden auf Mikrosekunden verschoben, da Millisekunden nicht genau genug sind. Kalender-Apps müssen ein Datumskonzept haben, das an einem lokalen Kalendertag auftritt, unabhängig davon, ob Sie sich in derselben Zeitzone befinden, in der Sie das Ereignis erstellt haben.
Alan Shutko
1
@AlanShutko Und ja, diese "zusätzlichen Daten", die benötigt werden, sind Dinge wie die lokale Zeitzone und Tage sowie alle anderen wichtigen Daten, die erfasst werden müssen. Dies sind alles nur Abstraktionen, jedoch zu einem bestimmten Zeitpunkt, auch wenn der Zeitpunkt für Ihren Algorithmus nicht wichtig ist. Was die Nanosekunden- und sogar Mikrosekunden-Skala angeht, ist meine Antwort eher auf Web- und LOB-Software ausgerichtet. Ich bezweifle, dass die LHC-Sprache der Wahl C # oder Javascript ist.
maple_shaft
1
Millisekunden eignen sich hervorragend für wiederholbare physikalische Prozesse. Bei menschlicher Tätigkeit ist die entsprechende Einheit manchmal ein Nominaltag. Wenn sie beispielsweise am Ende des Tages versandt wird, steht sie drei Tage später am Bestimmungsort zur Verfügung.
Kevin Cline
In der Vergangenheit habe ich darüber nachgedacht, 64-Bit-Gleitkommazahlen für Zeitkoordinaten und vor allem für Zeitspannen zu verwenden, da Sie damit winzige Mengen mit großer Genauigkeit ausdrücken können, aber auch große Mengen, bei denen Genauigkeitsverluste keine Rolle spielen . (Was ist, wenn die Dinosaurier vor 65 Millionen Jahren starben?) Warum sollten sie vermieden werden?
Mike Nakis
Mike, ich denke, seine Sorge gilt der unvermeidlichen Rundung von FP-Werten, da diese von Dezimalwerten in Binärwerte konvertiert werden. Beispielsweise ist 0,3 eine sich wiederholende Dezimalzahl, wenn sie als binäre FP-Zahl ausgedrückt wird, und kann daher nicht genau dargestellt werden. Es ist nicht so, dass Ihnen die Kapazität fehlt, sondern es fehlt Ihnen die Präzision.
Michael Blackburn
2

Kurz gesagt, da sich die meisten computerbasierten Zeittypen darauf konzentrieren, das Zeit- und Zeitzonenproblem richtig zu behandeln.

Es gibt 2 Randfälle, die mit dem üblichen Ansatz nicht gut bedient werden. Festlegen eines Zeitpunkts, der auf der anderen Seite der Sommerzeit liegt, unter Verwendung der Ortszeit, die dann in der UTC von einer niedrigeren Abstraktionsebene konvertiert wird und Sie zu einer Stunde früher / später für Ihr Meeting veranlasst.

Die andere Methode modelliert (wie in der Frage angegeben) beliebige Datumsinformationen, z. B. die Aufzeichnung des Geburtsdatums einer Person. Stellen Sie sich den Fall vor, in dem zwei Personen gleichzeitig geboren werden, eine in Neuseeland und eine auf Hawaii. Die Wahrscheinlichkeit ist, dass sie unterschiedliche Geburtsdaten in ihren Pässen haben, und wenn die in Hawaii geborene Person nach Neuseeland zieht, werden sie als einen Tag älter angesehen als die in Neuseeland geborene Person, obwohl sie genau dieselbe Zeit gelebt hat.

Der Vorschlag in der Frage, das Datum auf eine Mittagszeit einzustellen, wird in UTC funktionieren, FAST überall. UTC-Offsets reichen von -12 bis +14, sodass es im Pazifik einige Stellen gibt, an denen dieser Ansatz fehlschlägt. Ich neige dazu, diese Datentypen als Zeichenfolgen im Format JJJJMMTT zu behandeln. Wenn ich Vergleichsberechnungen zwischen zwei Daten durchführen muss, kann dies sicher als Zeichenfolgenvergleich durchgeführt werden. Wenn Sie Delta-Vergleiche durchführen (z. B. zwischen dem Datum und dem aktuellen Datum oder bis zum Erreichen des Alters X), müssen Sie sicherstellen, dass alle Datumsangaben mit demselben UTC-Offset erstellt wurden, und können dann die Standard-Zeitfunktionen verwenden, um die Arbeit auszuführen.

Michael Shaw
quelle
3
Ich neige dazu , diese Datentypen als Strings zu behandeln, in einem Format JJJJMMTT, und wenn ich auf Vergleiche Berechnungen zwischen zwei Terminen zu tun, kann dies sicher als String - Vergleich durchgeführt werden. “ Das ist sicher klingt wie ein DateDatentyp, nur in getragen werden aString
Ross Patterson
Wie Sie bereits sagten, handelt es sich um eine Zeichenfolgendarstellung eines Datums, und im Gegensatz zum Originalposter wird das Datum nicht geändert, wenn Sie sich in einer UTC + 13-Zeitzone befinden.
Michael Shaw
2

Warum gibt es keinen echten "Nur-Datum" -Datentyp?

Aus den gleichen Gründen denke ich, dass DateTime-Werte im Allgemeinen in UTC angegeben werden: Einfachheit und Zuverlässigkeit . Der Zeitpunkt eines DateTime-Werts ist die Angabe eines einzelnen Zeitpunkts, der von Zeitzone, Sommerzeit, Kalender und anderen lokalen Anpassungen nicht betroffen ist. DateTime-Werte geben einen Zeitpunkt an (bis zur Grenze der Auflösung des Typs), keinen Zeitraum oder eine Reihe von Zeiten. Diese Einschränkungen ermöglichen den zuverlässigen, vorhersehbaren und unkomplizierten Vergleich von DateTime-Werten.

Der Versuch, ein Datum mit einem DateTime-Wert anzugeben, ähnelt dem Versuch, einen Punkt zum Angeben eines Bereichs zu verwenden.Sie können dies mithilfe einer Konvention bewerkstelligen, beispielsweise "Dieser Punkt stellt den Mittelpunkt eines Kreises mit einem Radius von 100 m dar", aber da gibt es viele Probleme: Jeder muss dieselbe Konvention verwenden, und Sie müssen eine Reihe von Konventionen schreiben Durch die Unterstützung von Code wird die Arbeit mit dem falschen Typ weniger schmerzhaft und es ist so gut wie garantiert, dass Sie irgendwann einen Bereich angeben müssen, der größer oder kleiner als der herkömmliche Bereich ist. So ist es auch mit Datumsangaben: Sie können "Mittag" als herkömmliche Zeit für die Angabe von Datumsangaben verwenden, aber dann gelangen Sie in Zeitzonen, da die Benutzer Datumsangaben eher in ihrer Ortszeit als in UTC erwarten. Und selbst wenn Sie eine zufriedenstellende Methode zur Angabe eines Datums mithilfe von DateTime finden, benötigen Sie weitere Informationen, um festzustellen, ob es sich um ein absolutes oder ein relatives Datum handelt: Ist es der 4. Juli? 1776 oder jeden 4. Juli? Was ist, wenn Sie mit einer anderen Periode wiederholen möchten? Und Kalender haben alle möglichen verrückten Probleme: Manche Monate sind länger als andere, manche Jahre länger als andere, manche Tage sogar länger als andere, und manche Kalender weisen Lücken auf. Sie möchten diese Probleme nicht nur für ganze Tage lösen, da die gleichen Probleme für kürzere Zeiträume auftreten: Sie möchten wahrscheinlich in der Lage sein, Code zu schreiben, der "1 Tablette alle 4 Stunden einnehmen" genauso schnell wie "die" Gruppe trifft sich an jedem dritten Freitag. "

Die Arbeit mit Daten ist also mit vielen Komplikationen verbunden. Es ist relativ einfach (kein Wortspiel beabsichtigt), einen Typ anzugeben, der einen Zeitpunkt angibt und wie eine Zahl damit arbeitet, es ist jedoch äußerst schwierig, einen Typ anzugeben, der alle Arten der Verwendung von Datumsangaben berücksichtigt.

Wie andere betont haben, gibt es Sprachen und Bibliotheken, die Datumsangaben gut unterstützen, und es ist oft eine gute Idee, sie zu verwenden, da es ziemlich schwierig ist, datumsbezogenen Code genau zu finden.

Caleb
quelle
2
"Es ist schwierig, einen Typ bereitzustellen, der alle Arten der Verwendung von Daten behandelt." Es ist wahr, weshalb es eine schreckliche Idee ist, einen einzigen Typ bereitzustellen, um alles zu tun. Die ersten Java-Releases lieferten nur java.util.Date und das Ergebnis war schrecklich. Dann fügten sie eine komplexe java.util.Calendar-Hierarchie hinzu, und es wurde nicht viel besser.
Kevin Cline
1
@ Kevincline Stimme voll und ganz zu. OP hat keine Sprache angegeben, deshalb habe ich mich um Allgemeingültigkeit bemüht.
Caleb,
" Aus den gleichen Gründen denke ich, dass DateTime-Werte im Allgemeinen in UTC angegeben werden " ... Oh, wäre das wahr ? Es ist 2015, und es wird immer noch viel Code in der Zeitzone des Autors geschrieben :-(
Ross Patterson
1
Ich habe mich in der Tat gefragt, warum es keine allgemein anerkannte Konvention gibt, die Daten betrifft. Ihr "Verwenden eines Punktes, um einen Bereich darzustellen" fasst meine Frustration perfekt zusammen.
Michael Blackburn
2

Warum gibt es keinen echten "Nur-Datum" -Datentyp?

Es gibt viele solcher Typen in verschiedenen Bibliotheken für verschiedene Sprachen. Es gibt mit ziemlicher Sicherheit eine für Ihre aktuelle Sprache. Das Java-Paket util hatte eine schreckliche API für Zeitberechnungen, aber die Einführung des Pakets java.time hat das Leben viel besser gemacht. Siehe java.time.LocalDate (Jahr-Monat-Tag-Wert) oder java.time.MonthDay (Monat-Tag-Zahl).

Kevin Cline
quelle
1

Die kalendarische Manipulation ist einer der am wenigsten verstandenen Aspekte des Rechnens. Es wurden ganze Bücher zum Thema geschrieben. @MichealBlackburn fragt zu Recht nach einem Nur-Datum-Datentyp, der nicht bis zu einem Punkt auf einer Zeitachse aufgelöst wird, der einer Neuinterpretation unterliegt. In der Vergangenheit gab es berechtigte Streitigkeiten über die Bedeutung eines Datums. Man muss nicht weiter suchen als die Übernahme des Gregorianischen Kalenders, um herauszufinden, wie komplex es werden kann. Darüber hinaus haben die Jahre nicht immer am 1. Januar begonnen, selbst in Westeuropa und seinen Kolonien ( z. B. begannen Großbritannien und das britische Amerika das Jahr am 25. März).

Ross Patterson
quelle
1
Dies ist richtig. Die Kalender-FAQ, die ich in meiner Antwort zitiere, ist eine ausgezeichnete Quelle, um die Komplexität und Feinheiten von Clandar-Manipulationen zu entdecken
Michael Le Barbier Grünewald
-2

Als Antwort auf:

Nun, ich möchte ehrlich wissen, warum fast jede Sprache nur einen Datentyp dafür hat.

Der häufigste Grund könnte sein, "weil es nicht notwendig ist". Wenn Sie eine Datumszeit wünschen, für die Stunden, Minuten, Sekunden usw. keine Rolle spielen, initialisieren Sie sie einfach folgendermaßen:

date = new DateTime(year, month, day, 0, 0, 0);

Wenn Sie möchten, können Sie DateTime selbst erweitern:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Hinweis: Ich ignoriere absichtlich die Standardzeit und die Zeitzone. Es spielt keine Rolle, auf was Sie sie einstellen, solange sie für alle gleich sind Date. Sie können sich für UTC aussprechen. Sie können die Zeitzone angeben, in der sich Ihr Server befindet - so oder so halte ich es nicht für wichtig, einen ungenauen Wert wie diesen darzustellen Date. Das Gleiche gilt für die Standardzeit - Sie können es auf 0 setzen, Sie können es auf 12 setzen. Es spielt keine Rolle. Wenn Facebook mir um 00:01 Uhr eine Geburtstagsbenachrichtigung sendet, ich aber um 23:59 Uhr geboren bin, ist es mir egal und ich werde nicht beleidigt sein, dass sie länger als 12 Stunden frei waren.

Das obige ist in Java, würde aber in jeder Sprache mit DateTimeund Vererbung ähnlich funktionieren . Java hat tatsächlich zahlreiche Möglichkeiten, dies zu lösen, und die oben genannten sind veraltet (sie möchten, dass Sie sie Calendarjetzt verwenden). Aber wie andere in Kommentaren gepostet haben, bieten einige Sprachen tatsächlich eine Klasse an, vermutlich aus genau diesem Grund. Date

Höchstwahrscheinlich ist jede DateImplementierung nur ein Wrapper für die Sprache DateTimeund setzt die Zeit auf Null. Andernfalls benötigen Sie doppelten Code, um Probleme wie die Anzahl der Tage zwischen zwei Dates / DateTimes zu lösen oder ob zwei Dates gleich sind (Was ist mit dem 29. Februar und dem 1. März?). Solche Dinge werden normalerweise in der DateTimeKlasse gelöst . Es ist sinnvoll, denselben Code für a erneut zu verwenden Date.

Shaz
quelle
4
-1: Verwenden Sie LocalDate, wenn Sie nur Jahr + Monat + Tag möchten. Die Verwendung von DateTime für diesen Zweck führt zu Fehlern, wenn ein anderer Programmierer DateTime erkennt und davon ausgeht, dass es sich um einen Moment handelt.
Kevin Cline
@ Kevincline Ich fand das nicht notwendig, weil diese Frage sprachunabhängig ist. Ich würde auch denken, dass es offensichtlich ist, dass die Verwendung von Code mit der Bezeichnung "Veraltet" ein Szenario ist, das auf eigenes Risiko erfolgt. Noch wichtiger ist , habe ich nur , dass Sie als ein Beispiel für etwas , in einem Szenario zu tun , wo eine Sprache nicht eine hat LocalDate, oder DateTypklasse und Sie müssen ‚Roll-your-own‘.
Shaz
1
"Es ist jedoch notwendig" für einen klaren, präzisen und korrekten Code, der Geschäftsregeln zur Zeit enthält (im Gegensatz zur physischen Zeit). Wenn die Bibliothek keine Typen für die Nennzeit bereitstellt, muss der Programmierer sie erfinden, und die Art und Weise, dies zu tun, beginnt nicht mit "DateTime".
Kevin Cline
@ Kevincline Ich sehe nicht, wie der Code weniger klar oder prägnant wäre. Was ist aus Sicht eines Programmierers der Unterschied zwischen new Date(2000, 1, 1);und new Date(2000, 1, 1);? Kannst du sagen, welche Stunden, Minuten und Sekunden leer sind? Wenn Sie sich über zusätzliche Funktionen besorgt zeigt sich (wie setMinutes ()), dann könnte man die Route der gehen mit DateWrap DateTimeanstatt von ihm erben, und dann setzen Sie nur setYear, setMonth, SetDay, etc. Und es ist sicherlich nicht weniger korrekt als die verwendete DateTime der Bibliothek.
Shaz
Mein Hintergrund ist größtenteils C #, das kein Konstrukt analog zu LocalDate hat. Wir haben einfach nur DateTime und durchwühlen anscheinend.
Michael Blackburn