Frage

Betrachten Sie das folgende Programm:

DateTime dateTime = new DateTime(634546165144647370);
SqlDateTime sqlDateTime = new SqlDateTime(dateTime);

Console.WriteLine("dateTime.TimeOfDay    = " + dateTime.TimeOfDay);
Console.WriteLine("sqlDateTime.TimeOfDay = " + sqlDateTime.Value.TimeOfDay);
Console.ReadLine();

Das wird die folgende Ausgabe haben:

dateTime.TimeOfDay    = 10:21:54.4647370  
sqlDateTime.TimeOfDay = 10:21:54.4630000

Was mir seltsam ist, ist, dass .464737 auf 0,463 gerundet wurde. Sollte das nicht auf 0,464 abgerundet?

Ich nehme an, ich habe keinen Fehler im .NET -Code gefunden, daher lautet die Frage:

Warum rundete es zu dem, was es tat?Und wie kann ich Client -Seitenrunden bekommen, die das tun, was SQLServer tun wird?

Als Randnotiz habe ich diese Datumszeit in einer SQL -Server -Datenbank (in einer Spalte in DateTime) gespeichert und sie erneut herausgezogen und es kam als heraus 10:21:54.4670000. Also bin ich wirklich verwirrt. (Ich dachte, SQLDATETIME würde mit dem übereinstimmen, was SQL Server tun würde.)

Notiz: Da ich ODATA verwende, kann ich DateTime2 in SQL Server nicht verwenden.

War es hilfreich?

Lösung

SQL Server DATETIME Hat eine Genauigkeit von 3,33 ms - daher können Sie nicht alle möglichen Werte erhalten, und es besteht eine gute Chance .464 war einfach so ein Wert.

Auf SQL Server 2008 können Sie verwenden DATETIME2 oder TIME(x) DataTypen, die eine Genauigkeit auf 100 Ns haben - das sollte für die "reguläre" Verwendung reichlich genug sein

Andere Tipps

SQL Server datetype Datentyp ist intern zwei 32-Bit-Wörter (Ganzzahlen). Das Wort hoher Ordnung ist der Versatz in Tagen, seit die Epoche (Nullpunkt) des von SQL Server verwendeten internen Kalenders: diese Epoche 1. Januar 1900 00: 00: 00.000 ist. Das Wort niedriger Ordnung ist der Offset in Millisekunden seit dem Day-Start (00: 00: 00.000/Mitternacht).

Aus historischen Gründen beträgt die Präzision des Wortes niedriger Ordnung 1 Millisekunde; Die Genauigkeit beträgt 1/300. Sekunde (!?). Das bedeutet, dass eine bestimmte Punkt-in-Zeit auf ein Inkrement von 0, 3 oder 7 Millisekunden gerundet ist.

Um die Konvertierung in der Art und Weise durchzuführen, in der SQL-Server dies tut, machen Sie Folgendes: Nehmen Sie den Millisekundenabschnitt der tatsächlichen Zeit, einen Wert von 0-999, Modulo 100. Dadurch gibt es die Ziffer mit geringer Ordnung, einen Wert aus dem Wert 0-9. Wenn also die aktuelle Zeit 23: 57: 23.559 beträgt, beträgt die Millisekundenkomponente 559. Modulo 100 Sie erhalten 9.

  1. Die Werte 0 und 1 sind auf 0 "abgerundet".
  2. Die Werte 2, 3 und 4 sind auf 3 "abgerundet".
  3. Die Werte 5, 6, 7 und 8 sind auf 7 "abgerundet".
  4. Ein Wert von 9 ist abgerundet HOCH zu 0. Dies hat einen ziemlich unangenehmen und bösen Nebeneffekt: Wenn der Millisekundenabschnitt der Zeit 999 ist, wird 1 Millisekunde angekreuzt. Dies bedeutet, dass die Zeit 23: 59: 59.999 auf abgerundet ist DER NÄCHSTE TAG. Die Konvertierung von '31 Dez 2010 23: 59: 59,999 'ergibt einen DateTime -Wert von ... 1. Januar 2011 00: 00: 00.000.

Brillant! Oder so.

Siehe den Abschnitt "Bemerkungen" unter SQL Server 2005 Bol hier: http://msdn.microsoft.com/en-us/library/ms187819(v=sql.90).aspx

Das Ergebnis all dessen ist, dass Sie die offensichtliche Überprüfung für einen Datumsbereich/Zeitraum nicht durchführen können ... so etwas wie

where myDateColumn between '1 September 2011 00:00:00.000'
  and '30 September 2011 23:59:59.999'

Da das möglicherweise einen [kleinen] Datenback aus der nächsten Periode einbringt. Und du kannst nicht sagen

where myDateColumn between '1 September 2011 00:00'
  and '30 September 2011 23:59:59'

Da dies möglicherweise Daten ausschließt, die in den Zeitraum gehören. Stattdessen müssen Sie so etwas sagen

  • where myDateColumn >= '1 September 2011 00:00:00.000' and myDateColumn < '1 October 2011 00:00:00.000', oder

  • where myDateColumn >= '1 September 2011 00:00:00.000' and myDateColumn <= '30 September 2011 23:59:59.997'

Es sollte erwähnt werden, dass smalldatetime, die eine Präzision von 1 Minute hat, weist das gleiche falsche Verhalten auf: Wenn die Sekundenkomponente der Zeit 29,998 Sekunden oder weniger beträgt, ist es auf die nächste Minute abgerundet; Wenn 29.999 oder höher, ist es abgerundet HOCH bis zur nächsten Minute, also der Wert 31 Dec 2010 23:59:30.000' winds up as asmalldatetimevalue of1. Januar 2011 00: 00: 00`.

Dies hat alle möglichen Auswirkungen, insbesondere WRT auf Abrechnungssysteme und dergleichen.

Ich würde sagen, wenn Präzision für Sie wichtig ist, speichern Sie Ihre Datums-/Uhrzeitwerte in SQL Server als Zeichenfolgen in ISO 8601 Format, so etwas wie 2011-10-30T23:59:55.1234 (oder die äquivalente "kompakte" Form (20111030T235955.1234). ISO 8601 sammelt und vergleicht es richtig; Es konvertiert leicht und ist menschlich lesbar. Noch besser teilen Sie es in zwei Spalten auf - eine für das Datum (2011-10-30) und eins für die Zeit (23:59:55.1234). Fügen Sie dann eine dritte, berechnete Spalte hinzu, um alles zusammenzustellen:

create table foo
(
  ...
  transaction_date char(10) not null ,
  transaction_time char(12) not null ,
  ...
  iso8601_transaction_datetime as transaction_date + 'T' + transaction_time ,
  ...
)

Eine ziemlich gute Zusammenfassung von ISO 8601 ist bei http://www.cl.cam.ac.uk/~mgk25/iso-time.html. Wikipedia hat auch ziemlich gute Informationen: http://en.wikipedia.org/wiki/iso_8601.

Sqldatetime -Struktur

Repräsentiert die Datums- und Uhrzeitdaten, die vom 1. Januar 1753 bis 31. Dezember 9999 bis zu einer Genauigkeit von 3,33 Millisekunden in einer Datenbank gespeichert oder abgerufen werden sollen. Die SQLDATETIME -Struktur hat eine andere zugrunde liegende Datenstruktur als entsprechend .NET -Framework -Typ DateTime, die jederzeit zwischen 12:00:00 Uhr 1/1/0001 und 23:59:59 Uhr am 31.12.9999 zu Die Genauigkeit von 100 Nanosekunden. SQLDATETIME speichert den relativen Unterschied tatsächlich auf 00:00:00 Uhr 1/1/1900. Daher wird eine Konvertierung von "00:00:00 Uhr 1/1/1900" in eine Ganzzahl zurückgegeben. 0.

Ich würde argumentieren, dass Sqldatetime innerhalb dieser Genauigkeit von 3,33 ms liegt.

Der DateTime Value -Typ repräsentiert Daten und Uhrzeiten mit Werten zwischen 12:00:00 Uhr Mitternacht, 1. Januar 0001 Anno Domini (gemeinsame Ära) bis 11:59:59 Uhr, 31. Dezember 9999 n. Chr.

Als Randnotiz habe ich diese Datumszeit in einer SQL -Server -Datenbank (in einer Spalte in DateTime) gespeichert und sie erneut herausgezogen und es wurde als 10: 21: 54.4670000 herausgestellt. Also bin ich wirklich verwirrt. (Ich dachte, SQLDATETIME würde mit dem übereinstimmen, was SQL Server tun würde.)

Die Zeitwerte werden in 100-Nanosekunden-Einheiten gemessen, die als Zecken bezeichnet werden, und ein bestimmtes Datum ist die Anzahl der Zecken seit 12:00 Uhr Mitternacht, 1. Januar 0001 n. . Ein Zeckenwert von 31241376000000000L repräsentiert beispielsweise das Datum Freitag, 01. Januar, 0100 12:00:00 Mitternacht. Ein DateTime -Wert wird im Kontext eines expliziten oder Standardkalenders immer ausgedrückt.

und

Intern werden alle DateTime-Werte als Anzahl der Zecken (die Anzahl von 100-Nanosekunden-Intervallen) dargestellt, die seit 12:00:00 Uhr Mitternacht, 1. Januar 0001 verstrichen sind wird angezeigt, wenn Sie in einem Benutzeroberflächenelement angezeigt werden oder wenn Sie in eine Datei geschrieben wurden. Das Erscheinungsbild eines DateTime -Wertes ist das Ergebnis einer Formatierungsoperation. Das Formatieren ist der Prozess der Konvertierung eines Wertes in seine String -Darstellung.

Da das Erscheinungsbild von Datums- und Uhrzeitwerten von Faktoren wie Kultur, internationalen Standards, Anwendungsanforderungen und persönlichen Präferenzen abhängt, bietet die DateTime -Struktur eine große Flexibilität bei der Formatierungsdatum- und Uhrzeitwerte durch die Überlastung seiner ToString -Methode. Die Standard -Methode für datetime.toString () gibt die Zeichenfolgendarstellung eines Datums- und Zeitwerts mit dem kurzen Datum und des langjährigen Musters der aktuellen Kultur zurück. Das folgende Beispiel verwendet die Standard-Methode datetime.toString (), um das Datum und die Uhrzeit mit dem kurzen Datum und dem langjährigen Muster für die En-US-Kultur, die aktuelle Kultur auf dem Computer, auf dem das Beispiel ausgeführt wurde, anzuzeigen.

Es sieht so aus, als ob DateTime innerhalb von 100 ns genau ist, was sich um den Unterschied handelt, den Sie erlebt haben.

Als Randnotiz habe ich diese Datumszeit in einer SQL -Server -Datenbank (in einer Spalte in DateTime) gespeichert und sie erneut herausgezogen und es wurde als 10: 21: 54.4670000 herausgestellt. Also bin ich wirklich verwirrt. (Ich dachte, SQLDATETIME würde mit dem übereinstimmen, was SQL Server tun würde.)

Dies liegt auch innerhalb der 3,33 ms Genauigkeit ... Wenn Sie etwas genauerer benötigen, müssen Sie SQL Server 2008 verwenden

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top