Die Frage in der Überschrift kann wohl etwas missverstanden werden. Es geht mir nicht darum, wie sowas implementiert werden kann, sondern vielmehr um eine "philosophische" Betrachtung des Themas.
Aufgekommen ist es bei mir, als ich im Rahmen einer Anwendung TimeSpan-Werte - also Objekte, die eine Dauer wiedergeben - in einer Datenbank speichern wollte, die den Timespan-Datentyp nicht unterstützt, wohl aber den Typ Datum bzw. DateTime.
Der Versuch, ein TimeSpan-Objekt mithilfe der im .NET-Framework zur Verfügung gestellten Umwandlungsmöglichkeiten - z.B. CType, DirectCast, System.Convert - in ein DateTime-Objekt zu überführen, schlug jedoch fehl. Auf der Suche nach einer Begründung, warum man das eine nicht in das andere umsetzen können soll, stieß ich in diversen Foren immer wieder auf das Totschlagargument, ein DateTime sei nunmal ein festgelegter Zeitpunkt und ein TimeSpan nur eine Zeitspanne, mit der man ohne einen Referenz-(Zeit-)Punkt keinen DateTime-Zeitpunkt bestimmen kann. Oder anders: TimeSpan ist was relatives, DateTime was absolutes.
Auf den ersten Blick leuchtet das ein, auf den zweiten Blick aber ergibt das keinen Sinn, vor allem wenn man auch mal andere Teile des .NET-Frameworks oder andere weitverbreitete Bibliotheken betrachtet.
Exkurs: DirectX
In Direct3D wird viel mit Punkten im 3D-Raum und aber auch mit Vektoren im 3D-Raum herumhantiert. Der Unterschied zwischen Punkt und Vektor ist tatsächlich mit dem Unterschied zwischen DateTime und TimeSpan vergleichbar. Der Punkt ist eine feste (absolute) Position, während der Vektor nur eine relative Position ohne festen Bezugspunkt angibt. Erst durch die Anwendung des Vektors auf einen Bezugspunkt (z.B. den Ursprung) erhalten wir einen definierten Punkt im Raum.
Wo auch immer jedoch in der DirectX-API ein Punkt (also eine absolute Position, z.B. die Kameraposition) definiert wird, kommt ein Vector3D zum Einsatz. Es gibt in DirectX einfach keine separate Point-Klasse. Wird die Definition eines Punkts erwartet, so ist der Typ des Parameters immer ein Vektor bei dem einfach implizit definiert wird, dass sein Bezugspunkt der Ursprung des Koordinatensystems ist.
Betrachtet man nun, wie ein Datum intern gehandhabt wird, sieht es hier doch genauso aus. Denn ein DateTime-Objekt speichert intern doch im Grunde nichts anderes als "die Zeitspanne, die seit dem 1.1.0001 0:00 Uhr vergangen ist" (siehe MSDN), womit auch ein DateTime tatsächlich nur eine TimeSpan mit einem festen Bezugspunkt - dem Zeitpunkt 1.1.0001 0:00 Uhr - darstellt.
Die kleinste Einheit darin ist 1 "Tick", wobei 1 Tick 100 Nanosekunden, also 1/10 Millisekunde entspricht. Über die Anzahl der Ticks seit dem 1.1.0001 n.Chr. wird also ein DateTime definiert. Der Unterschied zum TimeSpan? Keiner, denn auch ein TimeSpan definiert nur die Anzahl Ticks, die eine Zeitspanne dauert.
Wenn also DirectX einen Vektor als Punkt betrachten will und dabei einfach den Bezugspunkt als Ursprung des Koordinatensystem impliziert, wieso kann dann nicht auch ein TimeSpan als DateTime betrachtet werden, indem man eben das Ursprungsdatum 1.1.0001 0:00 Uhr als Bezugspunkt impliziert?
Zugegeben, als "streng-gläubiger" OOPler muss es einem in der Seele wehtun, solch blasphemische Betrachtungen zu lesen. Ein DateTime ist ein DateTime und ein TimeSpan ist ein TimeSpan - fertig.
Aus "praktischer Sicht" heraus sehe ich keinen Grund, warum man eine Zeitspanne von "20 Minuten" nicht in ein Datum "1.1.0001 0:20 Uhr" umwandeln können soll, um daraus wieder die Zeitspanne "20 Minuten" herzuleiten.
Im Grunde bietet das .NET-Framework sogar indirekt die Möglichkeit dieser Umwandlung. Sowohl DateTime als auch TimeSpan bieten mit der identisch benannten Eigenschaft "Ticks" die Möglichkeit, die 1/10 Millisekunden Dauer bzw. 1/10 Millisekunden, die zwischen dem 1.1.0001 0:00 Uhr und dem Datum liegen zu bestimmen. Und sowohl die DateTime wie auch die TimeSpan-Klasse verfügen über einen Konstruktor, mit dem man jeweils ein Objekt mit Hilfe dieser Anzahl an 1/10 Millisekunden instanzieren kann. So lässt sich aus einem TimeSpan-Objekt relativ einfach mit
Warum mich das ganze beschäftigt und ich es als störend empfinde, dass diese Form der Konvertierung nicht auch durch entsprechende Cast-Operatoren oder die System.Convert-Klasse unterstützt wird, ist der Umstand, dass ich in Umgebungen, in denen solche Konvertierungen typ-unabhängig funktionieren sollen, so zum Beispiel ein O/R-Mapper für Datenbanken, nun mehr oder weniger gezwungen bin, einen zu speichernden Typ separat darauf zu testen, ob er einem TimeSpan entspricht und das Ziel aber nur DateTime akzeptiert (oder umgekehrt), damit ich hier an System.Convert vorbei den Mechanismus über die Ticks-Konstruktoren implementieren kann.
/discuss
Aufgekommen ist es bei mir, als ich im Rahmen einer Anwendung TimeSpan-Werte - also Objekte, die eine Dauer wiedergeben - in einer Datenbank speichern wollte, die den Timespan-Datentyp nicht unterstützt, wohl aber den Typ Datum bzw. DateTime.
Der Versuch, ein TimeSpan-Objekt mithilfe der im .NET-Framework zur Verfügung gestellten Umwandlungsmöglichkeiten - z.B. CType, DirectCast, System.Convert - in ein DateTime-Objekt zu überführen, schlug jedoch fehl. Auf der Suche nach einer Begründung, warum man das eine nicht in das andere umsetzen können soll, stieß ich in diversen Foren immer wieder auf das Totschlagargument, ein DateTime sei nunmal ein festgelegter Zeitpunkt und ein TimeSpan nur eine Zeitspanne, mit der man ohne einen Referenz-(Zeit-)Punkt keinen DateTime-Zeitpunkt bestimmen kann. Oder anders: TimeSpan ist was relatives, DateTime was absolutes.
Auf den ersten Blick leuchtet das ein, auf den zweiten Blick aber ergibt das keinen Sinn, vor allem wenn man auch mal andere Teile des .NET-Frameworks oder andere weitverbreitete Bibliotheken betrachtet.
Exkurs: DirectX
In Direct3D wird viel mit Punkten im 3D-Raum und aber auch mit Vektoren im 3D-Raum herumhantiert. Der Unterschied zwischen Punkt und Vektor ist tatsächlich mit dem Unterschied zwischen DateTime und TimeSpan vergleichbar. Der Punkt ist eine feste (absolute) Position, während der Vektor nur eine relative Position ohne festen Bezugspunkt angibt. Erst durch die Anwendung des Vektors auf einen Bezugspunkt (z.B. den Ursprung) erhalten wir einen definierten Punkt im Raum.
Wo auch immer jedoch in der DirectX-API ein Punkt (also eine absolute Position, z.B. die Kameraposition) definiert wird, kommt ein Vector3D zum Einsatz. Es gibt in DirectX einfach keine separate Point-Klasse. Wird die Definition eines Punkts erwartet, so ist der Typ des Parameters immer ein Vektor bei dem einfach implizit definiert wird, dass sein Bezugspunkt der Ursprung des Koordinatensystems ist.
Betrachtet man nun, wie ein Datum intern gehandhabt wird, sieht es hier doch genauso aus. Denn ein DateTime-Objekt speichert intern doch im Grunde nichts anderes als "die Zeitspanne, die seit dem 1.1.0001 0:00 Uhr vergangen ist" (siehe MSDN), womit auch ein DateTime tatsächlich nur eine TimeSpan mit einem festen Bezugspunkt - dem Zeitpunkt 1.1.0001 0:00 Uhr - darstellt.
Die kleinste Einheit darin ist 1 "Tick", wobei 1 Tick 100 Nanosekunden, also 1/10 Millisekunde entspricht. Über die Anzahl der Ticks seit dem 1.1.0001 n.Chr. wird also ein DateTime definiert. Der Unterschied zum TimeSpan? Keiner, denn auch ein TimeSpan definiert nur die Anzahl Ticks, die eine Zeitspanne dauert.
Wenn also DirectX einen Vektor als Punkt betrachten will und dabei einfach den Bezugspunkt als Ursprung des Koordinatensystem impliziert, wieso kann dann nicht auch ein TimeSpan als DateTime betrachtet werden, indem man eben das Ursprungsdatum 1.1.0001 0:00 Uhr als Bezugspunkt impliziert?
Zugegeben, als "streng-gläubiger" OOPler muss es einem in der Seele wehtun, solch blasphemische Betrachtungen zu lesen. Ein DateTime ist ein DateTime und ein TimeSpan ist ein TimeSpan - fertig.
Aus "praktischer Sicht" heraus sehe ich keinen Grund, warum man eine Zeitspanne von "20 Minuten" nicht in ein Datum "1.1.0001 0:20 Uhr" umwandeln können soll, um daraus wieder die Zeitspanne "20 Minuten" herzuleiten.
Im Grunde bietet das .NET-Framework sogar indirekt die Möglichkeit dieser Umwandlung. Sowohl DateTime als auch TimeSpan bieten mit der identisch benannten Eigenschaft "Ticks" die Möglichkeit, die 1/10 Millisekunden Dauer bzw. 1/10 Millisekunden, die zwischen dem 1.1.0001 0:00 Uhr und dem Datum liegen zu bestimmen. Und sowohl die DateTime wie auch die TimeSpan-Klasse verfügen über einen Konstruktor, mit dem man jeweils ein Objekt mit Hilfe dieser Anzahl an 1/10 Millisekunden instanzieren kann. So lässt sich aus einem TimeSpan-Objekt relativ einfach mit
new DateTime(timeSpan.Ticks)
ein DateTime-Objekt herleiten, mit dem es einem z.B. möglich wird, den Wert auch in solchen Datenbanken zu speichern, die nur DateTime-Typen, aber keine TimeSpan-Typen unterstützen (SQLite wäre so ein Beispiel). Anders herum kann solche ein DateTime-Objekt wieder mit new TimeSpan(dateTime.Ticks)
in ein TimeSpan-Objekt überführt werden.Warum mich das ganze beschäftigt und ich es als störend empfinde, dass diese Form der Konvertierung nicht auch durch entsprechende Cast-Operatoren oder die System.Convert-Klasse unterstützt wird, ist der Umstand, dass ich in Umgebungen, in denen solche Konvertierungen typ-unabhängig funktionieren sollen, so zum Beispiel ein O/R-Mapper für Datenbanken, nun mehr oder weniger gezwungen bin, einen zu speichernden Typ separat darauf zu testen, ob er einem TimeSpan entspricht und das Ziel aber nur DateTime akzeptiert (oder umgekehrt), damit ich hier an System.Convert vorbei den Mechanismus über die Ticks-Konstruktoren implementieren kann.
/discuss
Weltherrschaft erlangen: 1%
Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
Danke.
Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
Danke.