5

次のプログラムを検討してください。

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();

次の出力があります。

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

私にとって奇妙なのは、.464737が.463に丸められたことです。.464に丸めるべきではありませんか?

.NETコードにバグは見つかっていないと思いますので、質問は次のとおりです。

なぜそれはそれがしたことに丸めたのですか? SqlServerが実行することを実行するクライアント側の丸めを取得するにはどうすればよいですか?

ちなみに、この日時をSQL Serverデータベース(DateTime列)に保存して再度引き出したところ、10:21:54.4670000として出力されました。だから私は本当に混乱しています。(SqlDateTimeはSQL Serverが実行しようとしていたことと一致すると思いました。)

注: ODataを使用しているため、SQLServerでDateTime2を使用できません。

4

3 に答える 3

8

SQL ServerDATETIMEの精度は3.33ミリ秒です。したがって、すべての可能な値を取得することはできず、そのような値である可能性が高くなり.464ます。

DATETIME2SQL Server 2008では、100nsまでの精度を持つまたはデータ型を使用できます。TIME(x)これは「通常の」使用には十分なはずです。

于 2011-10-19T16:37:27.983 に答える
6

SQL Serverのdatetypeデータ型は、内部的には2つの32ビットワード(整数)です。上位ワードは、SQL Serverで使用される内部カレンダーのエポック(ゼロポイント)からの日数でのオフセットです。そのエポックは1900年1月1日00:00:00.000です。下位ワードは、1日の始まり(00:00:00.000 /真夜中)からのミリ秒単位のオフセットです。

歴史的な理由から、下位の単語の精度は1ミリ秒です。精度は1/300秒(!?)です。つまり、特定の時点は0、3、または7ミリ秒の増分に丸められます。

SQL Serverと同じ方法で変換を行うには、次の手順を実行します。検討中の実際の時間のミリ秒部分(0から999までの値、100を法とする値)を取得します。これにより、下位桁が得られます。 0-9。したがって、現在の時刻が23:57:23.559の場合、ミリ秒の成分は559です。モジュロ100は9になります。

  1. 値0および1は、0に「切り捨て」られます。
  2. 値2、3、および4は、3に「切り捨て」られます。
  3. 値5、6、7、および8は、7に「切り捨て」られます。
  4. 9の値は0に切り上げられます。これには、かなり不快で厄介な副作用があります。時間のミリ秒部分が999の場合、1ミリ秒刻みになります。これは、23:59: 59.999の時間が次の日に切り上げられることを意味します。したがって、「2010年12月31日23:59:59.999」を変換すると、日時の値は... 2011年1月1日00:00:00.000になります。

素晴らしい!か何か。

SQL Server 2005 BOLの「備考」セクションを参照してください:http://msdn.microsoft.com/en-us/library/ms187819(v = SQL.90).aspx

このすべての結果は、日付範囲/期間の明確なチェックを行うことができないということです...

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

それは潜在的に次の期間からの[小さな]データのチャンクをもたらすからです。そして、あなたは言うことはできません

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

その期間に属するデータが除外される可能性があるためです。代わりに、あなたは次のようなことを言わなければなりません

  • where myDateColumn >= '1 September 2011 00:00:00.000' and myDateColumn < '1 October 2011 00:00:00.000'、 また

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

1分の精度を持つ、は同じ偽の動作を示すことに注意してくださいsmalldatetime。検討中の時間の秒成分が29.998秒以下の場合、最も近い分に切り捨てられます。29.999以上の場合、次の分に切り上げられるため、値は31 Dec 2010 23:59:30.000' winds up as asmalldatetime value of1 Jan 2011 00:00:00`になります。

これには、特に課金システムなどに対するWRTなど、あらゆる種類の影響があります。

精度が重要な場合は、SQLServerに日付/時刻の値をISO8601形式の文字列として保存します2011-10-30T23:59:55.1234(または同等の「コンパクト」形式(20111030T235955.1234))。ISO8601は適切に照合および比較され、簡単に変換されます。人間が読める形式です。日付( 2011-10-30)用と時間( )用の2つの列に分割することをお勧めします23:59:55.1234。次に、3番目の計算列を追加して、すべてをまとめます。

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

ISO 8601のかなり良い要約は、http: //www.cl.cam.ac.uk/~mgk25/iso-time.htmlにあります。ウィキペディアにもかなり良い情報があります:http://en.wikipedia.org/wiki/ISO_8601

于 2011-10-19T17:22:45.160 に答える
1

SqlDateTime構造

1753年1月1日から9999年12月31日までの値の範囲で、データベースに格納またはデータベースから取得される3.33ミリ秒の精度の日付と時刻のデータを表します。SqlDateTime構造には、対応する.NET FrameworkタイプのDateTimeとは異なる基になるデータ構造があり、12:00:00AM1/1/0001から11:59:59PM12/31/9999までの任意の時間を表すことができます。 100ナノ秒の精度。SqlDateTimeは、実際には00:00:00AM1/1/1900までの相対的な差を格納します。したがって、「00:00:00 AM 1/1/1900」から整数に変換すると、0が返されます。

sqlDateTimeはその3.33ミリ秒の精度の範囲内であると私は主張します。

DateTime値タイプは、日付と時刻を表します。値の範囲は、0001年1月1日深夜12:00:00 Anno Domini(西暦)から9999年12月31日午後11:59:59までです。

ちなみに、この日時をSQL Serverデータベース(DateTime列)に保存して再度引き出したところ、10:21:54.4670000として出力されました。だから私は本当に混乱しています。(SqlDateTimeはSQL Serverが実行しようとしていたことと一致すると思いました。)

時間値はティックと呼ばれる100ナノ秒単位で測定され、特定の日付は、GregorianCalendarカレンダーの西暦0001年1月1日深夜12時以降のティック数です(うるう秒で追加されるティックを除く)。 。たとえば、ティック値31241376000000000Lは、1月1日金曜日の010012:00:00深夜の日付を表します。DateTime値は、常に明示的またはデフォルトのカレンダーのコンテキストで表されます。

内部的には、すべてのDateTime値は、0001年1月1日午前0時00分から経過したティック数(100ナノ秒間隔の数)として表されます。実際のDateTime値は、その値の方法とは無関係です。ユーザーインターフェイス要素に表示されたとき、またはファイルに書き込まれたときに表示されます。DateTime値の出現は、フォーマット操作の結果です。フォーマットは、値をその文字列表現に変換するプロセスです。

日付と時刻の値の外観は、文化、国際標準、アプリケーション要件、個人的な好みなどの要因に依存するため、DateTime構造は、ToStringメソッドのオーバーロードを通じて、日付と時刻の値をフォーマットする際に大きな柔軟性を提供します。デフォルトのDateTime.ToString()メソッドは、現在のカルチャの短い日付と長い時間のパターンを使用して、日付と時刻の値の文字列表現を返します。次の例では、デフォルトのDateTime.ToString()メソッドを使用して、例が実行されたコンピューター上の現在のカルチャであるen-USカルチャの短い日付と長い時間のパターンを使用して日付と時刻を表示します。

DateTimeは100ns以内で正確であるように見えます。これは、あなたが経験した違いとほぼ同じです。

ちなみに、この日時をSQL Serverデータベース(DateTime列)に保存して再度引き出したところ、10:21:54.4670000として出力されました。だから私は本当に混乱しています。(SqlDateTimeはSQL Serverが実行しようとしていたことと一致すると思いました。)

これも3.33ミリ秒の精度の範囲内です...3.33ミリ秒よりも正確なものが必要な場合は、SQLServer2008を使用する必要があります

于 2011-10-19T16:49:52.577 に答える