4 つの部分すべてで自分の質問に答えるために、いくつかの単体テストを実行しました。
###1:SQL Server はそれに応じて DateTime.UtcNow を保存しますか、それともサーバーがインストールされている場所のタイムゾーンに基づいて再度オフセットし、クエリを実行するとオフセットを逆にして返すのでしょうか?これを実行しました):
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT CAST(varchar としての値) 値 FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());
プレ>現地時間午後 1 時 30 分 (-7h、または UTC 午後 8 時 30 分) でのこの結果:
2010 年 6 月 3 日午後 8 時 30 分
プレ>次に、これを試しました:
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更");Console.ReadLine();cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());Console.WriteLine (「タイムゾーンをローカルに戻す」);
プレ>UTC 午後 9 時 25 分に実行され、返されました
2010 年 6 月 3 日午後 9 時 25 分
プレ>これを DateTime.Now と比較してください:
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更");Console.ReadLine();cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());Console.WriteLine (「タイムゾーンをローカルに戻す」);
プレ>午後 3 時 55 分 (ローカル; -7 時間) に実行され、返される:
2010 年 6 月 3 日午後 3 時 55 分
プレ>###2:それで、たとえば IDataReader 列から取得した後、クエリを実行し、オブジェクトから DateTime にキャストします。このキャストされた System.DateTime オブジェクトは、それが UTC DateTime インスタンスであることを既に認識していますか?それともオフセットされていると想定していますか?
どちらでもない。
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val 値 FROM testtbl";var retval =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + retval.Kind);Console.WriteLine("UTC:" + retval.ToUniversalTime ().ToString());Console.WriteLine("Local:" + retval.ToLocalTime().ToString());
プレ>この結果 (現地時間午後 1 時 58 分に実行) は次のとおりです。
Kind:UnspecifiedUTC:6/4/2010 3:58:42 AMLocal:6/3/2010 1:58:42 PM
プレ>つまり、
.ToUniversalTime()
現地時間から UTC 時間へのオフセットが 1 回ではなく 2 回 (??) になり、.ToLocalTime()
まったく相殺されませんでした。###3:ADO.NET はオフセットを SQL Server に渡し、SQL Server は DateTime.Now をオフセット メタデータと共に保存しますか?
単体テストを実行しなくても、答えは「DateTimeOffsetのみ」のSQLタイプであることが既にわかっています。 SQL の
datetime
オフセットは行いません。###4:このキャストされた System.DateTime オブジェクトは、それがオフセット時間であることを既に認識していますか、それとも UTC であると想定していますか?
ない。 SQL の DateTimeOffset 型は、.NET DateTimeOffset 構造体として返されます。
以下は、現地時間の午後 3 時 31 分に実行され、列
offval
は datetimeoffset SQL タイプです。cmd.CommandText ="INSERT INTO testtbl (offval) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); cmd.CommandText ="testtbl から offval 値を選択";object retvalobj =cmd.ExecuteScalar();Console.WriteLine("Type:" + retvalobj.GetType().Name);var retval =(DateTimeOffset)retvalobj;Console.WriteLine ("ToString():" + retval.ToString());Console.WriteLine("UTC:" + retval.ToUniversalTime().ToString());Console.WriteLine("Local:" + retval.ToLocalTime(). ToString());
プレ>その結果:
タイプ:DateTimeOffsetToString():6/3/2010 3:31:47 PM +00:00UTC:6/3/2010 3:31:47 PM +00:00Local:6/3/2010 8 :31:47 AM -07:00
プレ>驚くべき格差。
DateTime.UtcNow の代わりに DateTime.Now を使用して上記の質問 1 のテストに戻り、データベースに保存する前に ADO.NET が世界時に変換されないことを検証しました。
つまり、これは現地時間の午後 3 時 27 分 (-7h) に実行されます:
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)"; cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now)); cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更"); Console.ReadLine(); cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl"; Console.WriteLine(cmd.ExecuteScalar()); Console.WriteLine("タイムゾーンをローカルに戻す");
プレ>..返されました..
2010 年 6 月 3 日午後 3 時 27 分
プレ>これを現地時間午後 3 時 17 分に実行:
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val FROM testtbl";var result =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + result.Kind);Console.WriteLine("ToString():" + result. ToString());Console.WriteLine("1 分足します。UtcNow より大きいですか?" + (result.AddMinutes(1)> DateTime.UtcNow).ToString());Console.WriteLine("1 分足します。大きいですか? " + (result.AddMinutes(1)> DateTime.Now).ToString());Console.WriteLine("1分追加、UtcNow未満? " + (result.AddMinutes(1)
DateTime.UtcNow).ToString());Console.WriteLine("1 分減算します。今より大きいですか? " + (result.AddMinutes(-1)> DateTime.N ow).ToString());Console.WriteLine("1分引いて、UtcNow未満? " + (result.AddMinutes(-1) プレ> 結果:
Kind:UnspecifiedToString():6/3/2010 10:17:05 PMAdd 1 分、UtcNow より大きいですか? TrueAdd 1分、今より大きい? TrueAdd 1 分、UtcNow 未満ですか? FalseAdd 1分、今より短い? FalseSubtract 1 分、UtcNow より大きいか? FalseSubtract 1 分、Now より大きいか? TrueSubtract 1 分、UtcNow 未満ですか? TrueSubtract 1分、今より少ない?偽
プレ>これを DateTime.Now と比較してください:
cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val FROM testtbl";var result =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + result.Kind);Console.WriteLine("ToString():" + result. ToString());Console.WriteLine("1 分足します。UtcNow より大きいですか?" + (result.AddMinutes(1)> DateTime.UtcNow).ToString());Console.WriteLine("1 分足します。大きいですか? " + (result.AddMinutes(1)> DateTime.Now).ToString());Console.WriteLine("1分追加、UtcNow未満? " + (result.AddMinutes(1)
DateTime.UtcNow).ToString());Console.WriteLine("1 分減算します。今より大きいですか? " + (result.AddMinutes(-1)> DateTime.Now) .ToString());Console.WriteLine("1 分減算、UtcNow 未満ですか? " + (result.AddMinutes(-1) プレ> 午後 3 時 58 分に実行 (ローカル、-7 時間):
Kind:UnspecifiedToString():6/3/2010 3:59:26 PMAdd 1 分、UtcNow より大きいですか? FalseAdd 1分、今より大きい? TrueAdd 1 分、UtcNow 未満ですか? TrueAdd 1分、今より短い? FalseSubtract 1 分、UtcNow より大きいか? FalseSubtract 1 分、Now より大きいか? FalseSubtract 1 分、UtcNow 未満ですか? TrueSubtract 1分、今より少ない?真
プレ>