Note that there are some explanatory texts on larger screens.

plurals
  1. PODateTime - Strange daylight savings behaviour
    primarykey
    data
    text
    <p>My local timezone is (UTC+10:00) Canberra, Melbourne, Sydney</p> <p>Sat 31-Mar-2012 15:59 UTC = Sun 01-Apr-2012 02:59 +11:00<br> Sat 31-Mar-2012 16:00 UTC = Sun 01-Apr-2012 02:00 +10:00</p> <p>Daylight savings finishes at 3 AM first Sunday in April and the clock wind back 1 hour.</p> <p>Given the following code ....</p> <pre><code>DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal); DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal).AddMinutes(1); DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal); Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1); Console.WriteLine("{0:yyyy-MMM-dd HH:mm:ss.ffff K} ({1}) = {2:yyyy-MMM-dd HH:mm:ss.ffff K} ({3})", dt2, dt2.Kind, dt3, dt3.Kind); Console.WriteLine("{0} : {1} : {2}", dt1.ToUniversalTime().Hour, dt2.ToUniversalTime().Hour, dt3.ToUniversalTime().Hour); </code></pre> <p>I get the following output</p> <p>2012-Apr-01 02:59:00.0000 +11:00<br> 2012-Apr-01 03:00:00.0000 +10:00 (Local) = 2012-Apr-01 02:00:00.0000 +10:00 (Local)<br> 15 : 17 : 16</p> <p>Adding 1 minute to the original datetime makes the local time 3AM but also set the offset to +10 hours. Adding 1 minute to the UTC date and parsing correctly sets the local time to 2 AM with a +10 UTC offset.</p> <p>Repeating with</p> <pre><code>DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc); DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).AddMinutes(1); DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc); </code></pre> <p>or</p> <pre><code>DateTime dt1 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); DateTime dt2 = DateTime.Parse("31-Mar-2012 15:59", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).AddMinutes(1); DateTime dt3 = DateTime.Parse("31-Mar-2012 16:00", CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); </code></pre> <p>gives</p> <p>2012-Mar-31 15:59:00.0000 Z<br> 2012-Mar-31 16:00:00.0000 Z (Utc) = 2012-Mar-31 16:00:00.0000 Z (Utc)<br> 15 : 16 : 16 </p> <p>as expected</p> <p>Repeating again with</p> <pre><code>DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime(); DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime().AddMinutes(1); DateTime dt3 = new DateTime(2012, 03, 31, 16, 0, 0, DateTimeKind.Utc).ToLocalTime(); </code></pre> <p>gives the original</p> <p>2012-Apr-01 02:59:00.0000 +11:00<br> 2012-Apr-01 03:00:00.0000 +10:00 (Local) = 2012-Apr-01 02:00:00.0000 +10:00 (Local)<br> 15 : 17 : 16 </p> <p>Can anyone explain this ?</p> <p>Indecently if I use the TimeZoneInfo to convert from UTC to AUS Eastern Standard Time I get the correct time, but I lose the offset information in the DateTime instance as the DateTime.Kind == DateTimeKind.Unspecified</p> <p>== Additional scenario to highlight</p> <p>This is just simple timespan adding, starting with an NON-ambiguous UTC date, 1 minute before Daylight savings finishes.</p> <pre><code>DateTime dt1 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc); DateTime dt2 = new DateTime(2012, 03, 31, 15, 59, 0, DateTimeKind.Utc).ToLocalTime(); Console.WriteLine("Original in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1); Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.ToLocalTime()); Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1).ToLocalTime()); Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt1.AddMinutes(1)); Console.WriteLine("====================================================="); Console.WriteLine("Original in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.ToUniversalTime()); Console.WriteLine("Original in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2); Console.WriteLine("+ 1 Minute in Local : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1)); Console.WriteLine("+ 1 Minute in UTC : {0:yyyy-MMM-dd HH:mm:ss.ffff K}", dt2.AddMinutes(1).ToUniversalTime()); </code></pre> <p>gives</p> <p>Original in UTC : 2012-Mar-31 15:59:00.0000 Z<br> Original in Local : 2012-Apr-01 02:59:00.0000 +11:00<br> + 1 Minute in Local : 2012-Apr-01 <strong>02</strong>:00:00.0000 +10:00<br> + 1 Minute in UTC : 2012-Mar-31 <strong>16</strong>:00:00.0000 Z</p> <p>=====================================================</p> <p>Original in UTC : 2012-Mar-31 15:59:00.0000 Z<br> Original in Local : 2012-Apr-01 02:59:00.0000 +11:00<br> + 1 Minute in Local : 2012-Apr-01 <strong>03</strong>:00:00.0000 +10:00<br> + 1 Minute in UTC : 2012-Mar-31 <strong>17</strong>:00:00.0000 Z </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload