sql >> Databáze >  >> RDS >> Sqlserver

Jak je zpracováno časové pásmo v životním cyklu ADO.NET + SQL Server sloupec DateTime?

Provedl jsem několik jednotkových testů, abych odpověděl na mou vlastní otázku ve všech čtyřech částech.

###1:Ukládá SQL Server DateTime.UtcNow odpovídajícím způsobem, nebo jej znovu posunuje na základě časového pásma, kde je server nainstalován, a poté jej na dotaz vrací obrácený posun? Provedeno toto):

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@newval)";
cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT CAST(val as varchar) value FROM testtbl";
Console.WriteLine(cmd.ExecuteScalar());

Výsledek ve 13:30 místního času (-7 hodin nebo 20:30 UTC) byl:

Jun  3 2010 8:30PM

Pak jsem zkusil toto:

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@newval)";
cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));
cmd.ExecuteNonQuery();
Console.WriteLine("change time zone to utc");
Console.ReadLine();
cmd.CommandText = "SELECT CAST(val as varchar) value FROM testtbl";
Console.WriteLine(cmd.ExecuteScalar());
Console.WriteLine("change time zone back to local");

Provedeno ve 21:25 UTC, vrátilo se

Jun  3 2010 9:25PM

Porovnejte to s DateTime.Now:

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@newval)";
cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));
cmd.ExecuteNonQuery();
Console.WriteLine("change time zone to utc");
Console.ReadLine();
cmd.CommandText = "SELECT CAST(val as varchar) value FROM testtbl";
Console.WriteLine(cmd.ExecuteScalar());
Console.WriteLine("change time zone back to local");

Provedeno v 15:55 (místně; -7 h), vráceno:

Jun  3 2010  3:55PM

###2:Takže se na to zeptám a přetypuji to z objektu do DateTime poté, co to získám, řekněme, ze sloupce IDataReader. Ví již tento přetypovaný objekt System.DateTime, že se jedná o instanci UTC DateTime, nebo předpokládá, že byl posunut?

Ani jedno.

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@newval)";
cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT val value FROM testtbl";
var retval = (DateTime)cmd.ExecuteScalar();
Console.WriteLine("Kind: " + retval.Kind);
Console.WriteLine("UTC: " + retval.ToUniversalTime().ToString());
Console.WriteLine("Local: " + retval.ToLocalTime().ToString());

Výsledek (provedený ve 13:58 místního času) byl:

Kind: Unspecified
UTC: 6/4/2010 3:58:42 AM
Local: 6/3/2010 1:58:42 PM

Tedy .ToUniversalTime() skončilo posunutím z místního času na čas UTC ne jednou, ale dvakrát (??) a .ToLocalTime() se nakonec vůbec nekompenzovalo.

###3:Předává ADO.NET offset na SQL Server a SQL Server ukládá DateTime.Now s offsetovými metadaty?

Bez provedení jakýchkoliv testů jednotek je již známo, že odpověď je typu SQL „pouze s DateTimeOffset“. datetime SQL neprovádí offsety.

###4:Ví již tento přetypovaný objekt System.DateTime, že se jedná o časový posun, nebo předpokládá, že je to UTC?

Ani. Typ DateTimeOffset SQL je vrácen jako struktura .NET DateTimeOffset.

Následující bylo provedeno v 15:31 místního času, kde sloupec offval je typ SQL datetimeoffset,

cmd.CommandText = "INSERT INTO testtbl (offval) VALUES (@newval)";
cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT offval value FROM testtbl";
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());

Výsledkem bylo:

Type: DateTimeOffset
ToString(): 6/3/2010 3:31:47 PM +00:00
UTC: 6/3/2010 3:31:47 PM +00:00
Local: 6/3/2010 8:31:47 AM -07:00

Překvapivý nepoměr.

Když jsem se vrátil a provedl test pro otázku č. 1 výše pomocí DateTime.Now místo DateTime.UtcNow, ověřil jsem, že ADO.NET se NEkonvertuje na univerzální čas před uložením do databáze.

To znamená, že se to provedlo v 15:27 místního času (-7 h):

 cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@newval)";
 cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));
 cmd.ExecuteNonQuery();
 Console.WriteLine("change time zone to utc");
 Console.ReadLine();
 cmd.CommandText = "SELECT CAST(val as varchar) value FROM testtbl";
 Console.WriteLine(cmd.ExecuteScalar());
 Console.WriteLine("change time zone back to local");

.. vráceno ..

Jun  3 2010  3:27PM

Provedení v 15:17 místního času:

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@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("Add 1 minute, is greater than UtcNow? "
 + (result.AddMinutes(1) > DateTime.UtcNow).ToString());
Console.WriteLine("Add 1 minute, is greater than Now? "
 + (result.AddMinutes(1) > DateTime.Now).ToString());
Console.WriteLine("Add 1 minute, is less than UtcNow? "
 + (result.AddMinutes(1) < DateTime.UtcNow).ToString());
Console.WriteLine("Add 1 minute, is less than Now? "
 + (result.AddMinutes(1) < DateTime.Now).ToString());
Console.WriteLine("Subtract 1 minute, is greater than UtcNow? "
 + (result.AddMinutes(-1) > DateTime.UtcNow).ToString());
Console.WriteLine("Subtract 1 minute, is greater than Now? "
 + (result.AddMinutes(-1) > DateTime.Now).ToString());
Console.WriteLine("Subtract 1 minute, is less than UtcNow? "
 + (result.AddMinutes(-1) < DateTime.UtcNow).ToString());
Console.WriteLine("Subtract 1 minute, is less than Now? "
 + (result.AddMinutes(-1) < DateTime.Now).ToString());

Výsledek:

Kind: Unspecified
ToString(): 6/3/2010 10:17:05 PM
Add 1 minute, is greater than UtcNow? True
Add 1 minute, is greater than Now? True
Add 1 minute, is less than UtcNow? False
Add 1 minute, is less than Now? False
Subtract 1 minute, is greater than UtcNow? False
Subtract 1 minute, is greater than Now? True
Subtract 1 minute, is less than UtcNow? True
Subtract 1 minute, is less than Now? False

Porovnejte to s DateTime.Now:

cmd.CommandText = "INSERT INTO testtbl (val) VALUES (@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("Add 1 minute, is greater than UtcNow? "
 + (result.AddMinutes(1) > DateTime.UtcNow).ToString());
Console.WriteLine("Add 1 minute, is greater than Now? "
 + (result.AddMinutes(1) > DateTime.Now).ToString());
Console.WriteLine("Add 1 minute, is less than UtcNow? "
 + (result.AddMinutes(1) < DateTime.UtcNow).ToString());
Console.WriteLine("Add 1 minute, is less than Now? "
 + (result.AddMinutes(1) < DateTime.Now).ToString());
Console.WriteLine("Subtract 1 minute, is greater than UtcNow? "
 + (result.AddMinutes(-1) > DateTime.UtcNow).ToString());
Console.WriteLine("Subtract 1 minute, is greater than Now? "
 + (result.AddMinutes(-1) > DateTime.Now).ToString());
Console.WriteLine("Subtract 1 minute, is less than UtcNow? "
 + (result.AddMinutes(-1) < DateTime.UtcNow).ToString());
Console.WriteLine("Subtract 1 minute, is less than Now? "
 + (result.AddMinutes(-1) < DateTime.Now).ToString());

Provedeno v 15:58 (místně, -7 h):

Kind: Unspecified
ToString(): 6/3/2010 3:59:26 PM
Add 1 minute, is greater than UtcNow? False
Add 1 minute, is greater than Now? True
Add 1 minute, is less than UtcNow? True
Add 1 minute, is less than Now? False
Subtract 1 minute, is greater than UtcNow? False
Subtract 1 minute, is greater than Now? False
Subtract 1 minute, is less than UtcNow? True
Subtract 1 minute, is less than Now? True


  1. Jak provést FULL OUTER JOIN v ORACLE pomocí operátoru '+'?

  2. Mysql Codeigniter Active Record – Jak provedu dotaz where_in a vrátím správné pořadí výsledků?

  3. Vynulujte počítadlo automatického přírůstku v postgresu

  4. Jak obnovit právě smazané řádky v mysql?