it-swarm.com.de

Warum gibt es keinen Datentyp nur für ein Datum?

Eines der ersten Dinge, die ich über Datums- und Uhrzeitangaben in c # (und verschiedenen anderen Sprachen) gelernt habe, ist, dass ein Datum als DateTime gespeichert wird und die Zeitkomponente auf Mitternacht eingestellt ist. Es gibt keinen Unterschied zwischen "1. Januar 2017" und "1. Januar 2017 00: 00: 00.000". Wenn Sie nur ein Datum anzeigen müssen, können Sie Formatierungsfunktionen wie ToString verwenden, um den Zeitanteil zu entfernen.

Dies scheint viele Probleme zu verursachen, von denen ich einige hier auflisten werde:

  1. DateTime belegt mehr Speicherplatz als benötigt: 8 Byte anstelle der 3, die für ein einfaches Datum erforderlich sind.

  2. Die Verwendung von 00:00:00 für "kein Datum" verbindet "einen bekannten Wert von 0" mit "unbekanntem Wert". Dies scheint eher noobisch zu sein, genauso wie ein neuer Programmierer eine Nullzeichenfolge mit einer leeren Zeichenfolge verwechseln könnte. Null und leer sind unterschiedlich, und "keine Zeit" und "Mitternacht" sind unterschiedliche Ideen.

  3. Sie sehen Redewendungen wie diese, selbst in relativ einfachen Vergleichen:

    if (startDate >= myDateTime && myDateTime < endDate.AddDays(1))
    

    oder

    if (startDateTime >= myDate && myDate <= endDateTime.Date)
    

    statt einer viel einfacheren

    if (startDate >= myDate && myDate <= endDate)
    
  4. Wenn sich Systemkomponenten in verschiedenen Zeitzonen über Webdienste gegenseitig aufrufen und das Schema für diese Webdienste aus c # -Typen generiert wird, kann ein Zeitelement (so dass das resultierende Datum früh am Morgen auftritt) oder das Datum eingeführt werden Der Wert kann sich tatsächlich um einen Tag verschieben (z. B. ist das Enddatum tatsächlich der vorherige Tag zu einem Zeitpunkt am späten Abend). Dies kann es schmerzhaft machen, Werte zu übertragen, die in Bezug auf die Zeitzone agnostisch sind, z. ein Geburtsdatum oder ein Ablaufdatum der Kreditkarte.

SQL Server hat den Typ Date, in dem nur Monat, Tag und Jahr gespeichert sind.

XSD gibt verschiedene Datentypen für Datum, Uhrzeit und DateTime an.

Warum hat c # keinen solchen Typ?

Wie arbeiten Sie daran? Können c # -Eigenschaften beispielsweise so zugeordnet werden, dass sie als Datum anstelle einer DateTime serialisiert werden?

9
John Wu

Was ist ein Date?

Nehmen wir an, es ist Mittag in Ihrer Region. Sie werden auf Ihre Uhr schauen und so etwas wie 22/03/2017 12:00 sehen. Man könnte leicht sagen, dass dies das aktuelle Datum für alle anderen auf der Welt ist, oder?

Nicht wirklich. Wenn Sie in London oder in Russland oder den USA sind, ist Ihre Uhr in Bezug auf diese Orte wahrscheinlich nicht richtig. Ihre Uhr markiert die falsche Zeit für den Rest der Welt und für einige Orte sogar das falsche Datum. Wenn Sie über "die Welt" sprechen, macht es wenig bis gar keinen Sinn, ein Datum ohne Zeit zu haben, wenn Sie anfangen, Menschen außerhalb Ihrer Zeitzone in Betracht zu ziehen. Denken Sie nur daran, wie ärgerlich es ist, auf eine Website eines Ausländers zu gehen und zu sehen, dass der dort generierte benutzergenerierte Inhalt irgendwie aus der Zukunft stammt. Das passiert, wenn Sie Zeitzonen nicht berücksichtigen!

Hier setzt C # DateTime an.

DateTime ist nicht das übliche einfache Datum, das Sie möglicherweise für lokale Software benötigen, die nur von mir stammt. Es ist eine ziemlich leistungsfähige Datenstruktur, die die Absicht hatte, jeder App die universelle koordinierte Zeit zur Verfügung zu stellen. Der magische Teil der DateTime-Struktur besteht darin, dass Sie mit ein wenig Fummelei die richtige DateTime für jeden einzelnen Ort auf der Welt anzeigen können.

Die Idee hinter DateTime war, kein einfaches Datumsobjekt bereitzustellen, sondern etwas, mit dem Sie Datumsangaben auf der ganzen Welt darstellen können, auch mit unterschiedlichen Zeitzonen. Es wurde zum Nachdenken in globalen Anwendungen entwickelt und daher mit einer Reihe zusätzlicher Funktionen ausgestattet, die auf den ersten Blick nicht offensichtlich nützlich sind, aber dennoch viel Zeit für Benutzer sparen können, die Anwendungen entwickeln, die sich mit variablen Zeitzonen befassen müssen .

Es ist alles andere als perfekt, ja, aber es macht das, wofür es gedacht war - die Zeit auf universelle und etwas tragbare Weise darzustellen.

In gewisser Weise müssen Sie bei der Verwendung von C # bei der Entwicklung Ihrer App nicht nur Daten, sondern auch Zeiten berücksichtigen. Und das ist wirklich eine gute Sache - eine DateTime ist ein Referenzzeitpunkt relativ zu etwas, und wenn Sie Ihren Referenzpunkt ändern, muss der Wert für diese DateTime entsprechend handeln.

Um ganz fair zu sein, ich denke, C # ist eine der Sprachen, die dieses Ding richtig gemacht haben. Sie können ein Zeitintervall ohne Datum haben (TimeSpan ist dafür da), aber Sie können kein aussagekräftiges Datum für einen globalen Bereich ohne einen Referenzrahmen und eine damit verbundene Uhrzeit haben. Ich mochte DateTime überhaupt nicht, als ich die Sprache zum ersten Mal traf, aber nachdem ich eine App mit mehreren Zeitzonen entwickeln musste, verstand ich, warum diese Designentscheidung eigentlich eine kluge war.

16
T. Sar

Anthony Moore bietet einen Blogeintrag mit einigen historischen Anmerkungen speziell zu DateTime , einschließlich einer Diskussion der Art von Problemen, die Microsoft zu lösen versuchte. Es ist ein bisschen alt, bietet aber dennoch einige Einblicke.

Der größte Teil des Artikels befasst sich mit Zeitzonenproblemen und Abwärtskompatibilitätsproblemen. Es scheint, dass Microsoft im Laufe der Geschichte der .NET-Versionen erkannt hat, dass der Problembereich sehr komplex ist und alles, was sie getan haben, das Ergebnis eines Wunsches nach einem Kompromiss zwischen Funktionsreichtum und Einfachheit zu sein scheint. Hier ist ein interessantes Stück, das (sehr kurz) das Problem einer Nur-Datum-Darstellung anzusprechen scheint:

Betrachten Sie zunächst die Landschaft datums- und zeitbezogener Szenarien:

A. Legacy DateTime Interop (Datenbanken, COM, Win32 usw.).

B. Abstrakte DateTime-Szenarien (z. B. Startzeit speichern).

C. Nur-Datum-Szenarien.

D. Nur-Zeit-Szenarien.

E. Absolute Zeitszenarien. (z. B. Dateizeit).

F. Serverszenarien mit Daten aus mehreren Zeitzonen, in denen die ursprüngliche Ortszeit beibehalten werden muss.

Szenarien C-D werden möglicherweise noch besser von dedizierten Datums- und Uhrzeittypen verarbeitet. Diese Optionen sind noch in der Tabelle enthalten, obwohl sie nicht in der .NET 3.5-Version enthalten sind.

Es scheint also, dass sie haben einen Datums-Datentyp in Betracht gezogen haben und dieser noch auf dem Tisch lag, als dieser Blog geschrieben wurde. Eine weitere Erklärung finden Sie an anderer Stelle im Artikel:

Es bestand ein großer Wunsch, das Typensystem einfach zu halten, und während eine zeitzonenbewusste DateTime besser in der Lage war, absolute Zeitpunkte wie einen Datei-Zeitstempel darzustellen, wurde es unangenehm, bestimmte Dinge zu tun ... ganze Daten darzustellen , z.B Der Typ, den ein Kalendersteuerelement zurückgeben soll. Offensichtlich ist ein "Datum" -Typ eine noch bessere Möglichkeit, dies darzustellen, und viele Leute haben nach getrennten Datums- und Zeittypen gefragt, aber in V1.0 bestand der Wunsch, die Anzahl von beizubehalten Basistypen klein, um die Komplexität der Plattform zu begrenzen. Diese Funktionsanforderung ist definitiv noch in der Tabelle, obwohl sie für .NET 3.5 nicht geplant ist

Ich denke, die Antwort ist ... ja, sie haben darüber nachgedacht ... nein, sie haben es noch nicht getan, weil es bestimmte Probleme aufwirft und der Wunsch besteht, die gesamte Plattform einfach zu halten.

In der Zwischenzeit haben sie die neuere DateTimeOffset Struktur veröffentlicht, die einige der Zeitzonenprobleme behebt. Aber keine Nur-Datum-Ausgabe. Hoffentlich werden die Nur-Datum-Probleme als nächstes zur Prüfung anstehen.

3
John Wu

In den CLR-Standardbibliotheken gibt es keine solche Klasse, aber aus den von Ihnen identifizierten und anderen Gründen besteht häufig Bedarf an so etwas.

Sie können die "Noda" -Bibliothek für C # importieren und LocalDate verwenden, um ein Datum ohne eine bestimmte Zeit darzustellen.

Diese Klasse basiert auf einer ähnlichen Klasse aus der Java Bibliothek "Joda", die sich als so nützlich und gut geschrieben erwiesen hat, dass sie jetzt in die Java Standardbibliotheken importiert wurde: LocalDate

Bei der Konvertierung von einem LocalDate (ohne Zeit) in ein Standard DateTime (mit einer Zeitkomponente) zwingt die Bibliothek Sie, Ihre Annahmen explizit zu machen, sodass alle Arten von Edge-Fällen und vermieden werden Fehler, die Sie in Ihrer Frage und in der Diskussion über die Antwort von T. Sar identifiziert haben

3
Rich