TimeZoneTest.cs 20.1 KB
Newer Older
1 2 3
//
// TimeZoneTest.cs - NUnit Test Cases for the System.TimeZone struct
//
4 5 6
// Authors:
//	Martin Baulig (martin@gnome.org)
//	Sebastien Pouliot  <sebastien@ximian.com>
7 8
//
//   (C) 2002 Martin Baulig
9
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 11 12 13
//

using NUnit.Framework;
using System;
14
using System.IO;
15 16
using System.Threading;
using System.Globalization;
17
using System.Reflection;
18
using System.Runtime.Serialization.Formatters.Binary;
19 20 21

namespace MonoTests.System {

22
[TestFixture]
23
public class TimeZoneTest {
24 25 26

	private void CET (TimeZone t1) 
	{
27 28
		Assert.IsTrue("CET" == t1.StandardName || "W. Europe Standard Time" == t1.StandardName, "A01");
		Assert.IsTrue("CEST" == t1.DaylightName || "W. Europe Daylight Time" == t1.DaylightName, "A02");
29 30
	
		DaylightTime d1 = t1.GetDaylightChanges (2002);
31 32
		Assert.AreEqual("03/31/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "A03");
		Assert.AreEqual("10/27/2002 03:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "A04");
33
		Assert.AreEqual(36000000000L, d1.Delta.Ticks, "A05");
34 35
	
		DaylightTime d2 = t1.GetDaylightChanges (1996);
36 37
		Assert.AreEqual("03/31/1996 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "A06");
		Assert.AreEqual("10/27/1996 03:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "A07");
38
		Assert.AreEqual(36000000000L, d2.Delta.Ticks, "A08");
39 40
	
		DateTime d3 = new DateTime (2002,2,25);
41
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "A09");
42
		DateTime d4 = new DateTime (2002,4,2);
43
		Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "A10");
44
		DateTime d5 = new DateTime (2002,11,4);
45
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "A11");
46
	
47 48 49
		Assert.AreEqual(36000000000L, t1.GetUtcOffset (d3).Ticks, "A12");
		Assert.AreEqual(72000000000L, t1.GetUtcOffset (d4).Ticks, "A13");
		Assert.AreEqual(36000000000L, t1.GetUtcOffset (d5).Ticks, "A14");
50 51 52 53 54

		// Test TimeZone methods with UTC DateTime in DST.
		DateTime d6 = d4.ToUniversalTime ();
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "A15");
		Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "A16");
55 56 57 58
	}

	private void EST (TimeZone t1) 
	{
59 60
		Assert.IsTrue("EST" == t1.StandardName || "Eastern Standard Time" == t1.StandardName, "B01");
		Assert.IsTrue("EDT" == t1.DaylightName || "Eastern Daylight Time" == t1.DaylightName, "B02");
61 62

		DaylightTime d1 = t1.GetDaylightChanges (2002);
63 64
		Assert.AreEqual("04/07/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "B03");
		Assert.AreEqual("10/27/2002 02:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "B04");
65
		Assert.AreEqual(36000000000L, d1.Delta.Ticks, "B05");
66 67

		DaylightTime d2 = t1.GetDaylightChanges (1996);
68 69
		Assert.AreEqual("04/07/1996 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "B06");
		Assert.AreEqual("10/27/1996 02:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "B07");
70
		Assert.AreEqual(36000000000L, d2.Delta.Ticks, "B08");
71 72

		DateTime d3 = new DateTime (2002,2,25);
73
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "B09");
74
		DateTime d4 = new DateTime (2002,4,8);
75
		Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "B10");
76
		
77
		DateTime d5 = new DateTime (2002,11,4);
78
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "B11");
79

80 81 82
		Assert.AreEqual(-180000000000L, t1.GetUtcOffset (d3).Ticks, "B12");
		Assert.AreEqual(-144000000000L, t1.GetUtcOffset (d4).Ticks, "B13");
		Assert.AreEqual(-180000000000L, t1.GetUtcOffset (d5).Ticks, "B14");
83 84 85 86 87

		// Test TimeZone methods with UTC DateTime in DST.
		DateTime d6 = d4.ToUniversalTime ();
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "B15");
		Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "B16");
88
	}
89

90 91
	private void TST (TimeZone t1) 
	{
92 93
		Assert.AreEqual("Tokyo Standard Time", t1.StandardName, "C01");
		Assert.AreEqual("Tokyo Standard Time", t1.DaylightName, "C02");
94 95

		DateTime d3 = new DateTime (2002,2,25);
96
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "C09");
97
		DateTime d4 = new DateTime (2002,4,8);
98
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d4), "C10");
99
		DateTime d5 = new DateTime (2002,11,4);
100
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "C11");
101

102 103 104
		Assert.AreEqual(324000000000L, t1.GetUtcOffset (d3).Ticks, "C12");
		Assert.AreEqual(324000000000L, t1.GetUtcOffset (d4).Ticks, "C13");
		Assert.AreEqual(324000000000L, t1.GetUtcOffset (d5).Ticks, "C14");
105 106
	}

D
 
David Sheldon 已提交
107 108 109 110
	private void GMT (TimeZone t1) {
		// Probably wont work on MS.NET, but is better than nothing. Where do
		// we change our implementation to match theirs?
		
111
		Assert.AreEqual("GMT", t1.StandardName, "D01");
M
Marek Safar 已提交
112
		Assert.IsTrue("BST" == t1.DaylightName || "IST" == t1.DaylightName, "D02");
D
 
David Sheldon 已提交
113 114
	
		DaylightTime d1 = t1.GetDaylightChanges (2002);
115 116
		Assert.AreEqual("03/31/2002 01:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "D03");
		Assert.AreEqual("10/27/2002 02:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "D04");
117
		Assert.AreEqual(36000000000L, d1.Delta.Ticks, "D05");
D
 
David Sheldon 已提交
118 119
	
		DaylightTime d2 = t1.GetDaylightChanges (1996);
120 121
		Assert.AreEqual("03/31/1996 01:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "D06");
		Assert.AreEqual("10/27/1996 02:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "D07");
122
		Assert.AreEqual(36000000000L, d2.Delta.Ticks, "D08");
D
 
David Sheldon 已提交
123 124
	
		DateTime d3 = new DateTime (2002,2,25);
125
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "D09");
D
 
David Sheldon 已提交
126
		DateTime d4 = new DateTime (2002,4,2);
127
		Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "D10");
D
 
David Sheldon 已提交
128
		DateTime d5 = new DateTime (2002,11,4);
129
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "D11");
D
 
David Sheldon 已提交
130
	
131 132 133
		Assert.AreEqual(0L, t1.GetUtcOffset (d3).Ticks, "D12");
		Assert.AreEqual(36000000000L, t1.GetUtcOffset (d4).Ticks, "D13");
		Assert.AreEqual(0L, t1.GetUtcOffset (d5).Ticks, "D14");
134 135 136 137 138

		// Test TimeZone methods with UTC DateTime in DST.
		DateTime d6 = d4.ToUniversalTime ();
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "D15");
		Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "D16");
D
 
David Sheldon 已提交
139 140
	}

A
Alistair Bush 已提交
141 142 143 144 145
	private void NZST(TimeZone t1) {
		Assert.AreEqual("NZST", t1.StandardName, "E01");
		Assert.AreEqual("NZDT", t1.DaylightName, "E02");

		DaylightTime d1 = t1.GetDaylightChanges (2013);
146 147
		Assert.AreEqual("09/29/2013 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "E03");
		Assert.AreEqual("04/07/2013 03:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "E04");
A
Alistair Bush 已提交
148 149 150
		Assert.AreEqual(36000000000L, d1.Delta.Ticks, "E05");

		DaylightTime d2 = t1.GetDaylightChanges (2001);
151 152
		Assert.AreEqual("10/07/2001 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "E06");
		Assert.AreEqual("03/18/2001 03:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "E07");
A
Alistair Bush 已提交
153 154 155 156 157 158 159 160 161 162 163 164
		Assert.AreEqual(36000000000L, d2.Delta.Ticks, "E08");

		DateTime d3 = new DateTime(2013,02,15);
		Assert.AreEqual(true, t1.IsDaylightSavingTime (d3), "E09");
		DateTime d4 = new DateTime(2013,04,30);
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d4), "E10");
		DateTime d5 = new DateTime(2013,11,03);
		Assert.AreEqual(true, t1.IsDaylightSavingTime (d5), "E11");

		Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d3).Ticks, "E12");
		Assert.AreEqual(36000000000L /*hour*/ * 12L, t1.GetUtcOffset (d4).Ticks, "E13");
		Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d5).Ticks, "E14");
165 166 167 168 169

		// Test TimeZone methods with UTC DateTime in DST.
		DateTime d6 = d5.ToUniversalTime ();
		Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "E15");
		Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "E16");
A
Alistair Bush 已提交
170 171
	}

172
	[Test]
173 174 175 176
	public void TestCtors ()
	{
		TimeZone t1 = TimeZone.CurrentTimeZone;
		switch (t1.StandardName) {
177
			case "W. Europe Standard Time":
178 179 180 181
			case "CET":
				CET (t1);
				break;
			case "Eastern Standard Time":
182
			case "EST":
183 184
				EST (t1);
				break;
185 186 187
			case "Tokyo Standard Time":
				TST (t1);
				break;
D
 
David Sheldon 已提交
188 189 190
			case "GMT":
				GMT (t1);
				break;
A
Alistair Bush 已提交
191 192 193
			case "NZST":
				NZST (t1);
				break;
194
			default:
195
				NUnit.Framework.Assert.Ignore ("Your time zone (" + t1.StandardName + ") isn't defined in the test case");
196 197 198
				break;
		}
        }
199 200 201 202 203 204 205 206 207 208 209 210

	[Test]
	public void CurrentTimeZone_SerializationRoundtrip ()
	{
		TimeZone tz = TimeZone.CurrentTimeZone;
		BinaryFormatter bf = new BinaryFormatter ();
		MemoryStream ms = new MemoryStream ();
		bf.Serialize (ms, tz);

		ms.Position = 0;
		TimeZone clone = (TimeZone) bf.Deserialize (ms);

211 212
		Assert.AreEqual (tz.DaylightName, clone.DaylightName, "DaylightName");
		Assert.AreEqual (tz.StandardName, clone.StandardName, "StandardName");
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
	}

	static private byte[] serialized_timezone = {
		0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 
		0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x54, 
		0x69, 0x6D, 0x65, 0x5A, 0x6F, 0x6E, 0x65, 0x04, 0x00, 0x00, 0x00, 0x17, 0x6D, 0x5F, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x44, 0x61, 
		0x79, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x73, 0x0D, 0x6D, 0x5F, 0x74, 0x69, 0x63, 0x6B, 0x73, 0x4F, 
		0x66, 0x66, 0x73, 0x65, 0x74, 0x0E, 0x6D, 0x5F, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x4E, 0x61, 0x6D, 0x65, 0x0E, 0x6D, 
		0x5F, 0x64, 0x61, 0x79, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x03, 0x00, 0x01, 0x01, 0x1C, 0x53, 0x79, 0x73, 0x74, 
		0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2E, 0x48, 0x61, 0x73, 0x68, 0x74, 0x61, 0x62, 
		0x6C, 0x65, 0x09, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x29, 0x17, 0xD6, 0xFF, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x15, 
		0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x0A, 
		0x04, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 
		0x6E, 0x73, 0x2E, 0x48, 0x61, 0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x4C, 0x6F, 0x61, 0x64, 0x46, 
		0x61, 0x63, 0x74, 0x6F, 0x72, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x08, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x72, 0x65, 0x72, 
		0x10, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6F, 0x64, 0x65, 0x50, 0x72, 0x6F, 0x76, 0x69, 0x64, 0x65, 0x72, 0x08, 0x48, 0x61, 0x73, 0x68, 
		0x53, 0x69, 0x7A, 0x65, 0x04, 0x4B, 0x65, 0x79, 0x73, 0x06, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x00, 0x00, 0x03, 0x03, 0x00, 0x05, 
		0x05, 0x0B, 0x08, 0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 
		0x2E, 0x49, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x72, 0x65, 0x72, 0x24, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 
		0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2E, 0x49, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6F, 0x64, 0x65, 0x50, 0x72, 0x6F, 0x76, 0x69, 
		0x64, 0x65, 0x72, 0x08, 0xEC, 0x51, 0x38, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 
		0x00, 0x09, 0x05, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x08, 0xCC, 0x07, 0x00, 0x00, 0x08, 
		0x08, 0xD5, 0x07, 0x00, 0x00, 0x08, 0x08, 0xD2, 0x07, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x06, 
		0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x21, 0x53, 0x79, 0x73, 
		0x74, 0x65, 0x6D, 0x2E, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x44, 0x61, 0x79, 0x6C, 
		0x69, 0x67, 0x68, 0x74, 0x54, 0x69, 0x6D, 0x65, 0x03, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x05, 0x6D, 
		0x5F, 0x65, 0x6E, 0x64, 0x07, 0x6D, 0x5F, 0x64, 0x65, 0x6C, 0x74, 0x61, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0C, 0x00, 0x10, 0xFA, 0x0F, 
		0x3D, 0xF2, 0xBC, 0x88, 0x00, 0x50, 0xD5, 0xB1, 0xC1, 0x91, 0xBD, 0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x01, 0x07, 
		0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x50, 0x23, 0xFA, 0x07, 0x06, 0xC7, 0x88, 0x00, 0xD0, 0xE2, 0xC4, 0x0C, 0xAB, 0xC7, 
		0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0C, 0x0F, 
		0xEF, 0xAB, 0xC3, 0x88, 0x00, 0x90, 0xE7, 0xB0, 0x73, 0x4B, 0xC4, 0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x0B
	};

	[Test]
	[Category ("NotWorking")] 
	// 1.x - deserialize but strings are null
	// 2.x - eexception when creating a datetime with a negative value
	public void DeserializeKnownValue ()
	{
		MemoryStream ms = new MemoryStream (serialized_timezone);
		BinaryFormatter bf = new BinaryFormatter ();
		TimeZone tz = (TimeZone) bf.Deserialize (ms);
255 256
		Assert.AreEqual ("Eastern Daylight Time", tz.DaylightName, "DaylightName");
		Assert.AreEqual ("Eastern Standard Time", tz.StandardName, "StandardName");
257
	}
258

259 260 261 262 263 264
	[Test]
	public void ToLocalTimeAtDSTBoundaries ()
	{
		TimeZone tz = TimeZone.CurrentTimeZone;
		DateTime dst_start_utc = tz.GetDaylightChanges(2007).Start.ToUniversalTime ();

S
Stephane Delcroix 已提交
265
		if (dst_start_utc == DateTime.MinValue)
266
			Assert.Ignore ("Couldn't get beginning of daylight saving time in 2007.");
267 268 269 270 271
		Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Subtract (new TimeSpan (0, 1, 0))) < tz.ToLocalTime (dst_start_utc), "0:1:59 < 0:3:00");
		Assert.IsTrue (tz.ToLocalTime (dst_start_utc) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 1, 0))), "0:3:00 < 0:3:01");
		Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 1, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 59, 0))), "0:3:01 < 0:3:59");
		Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 59, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 0, 0))), "0:3:59 < 0:4:00");
		Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 0, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 1, 0))), "0:4:00 < 0:4:01");
272
	}
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
		[Test]
		public void GetUTCNowAtDSTBoundaries ()
		{
			TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 3, 5, DayOfWeek.Sunday);

			TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 10, 5, DayOfWeek.Sunday);

			TimeSpan delta = TimeSpan.FromMinutes(60.0);
			TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1970, 1, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
			TimeZoneInfo.TransitionTime startTrans = adjustment.DaylightTransitionStart;
			TimeZoneInfo.TransitionTime endTrans = adjustment.DaylightTransitionEnd;
			TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };

			TimeZoneInfo tzInfo = TimeZoneInfo.CreateCustomTimeZone("MY Standard Time", TimeSpan.Zero, "MST", "MST", "MDT", adjustments);

			// There is no .NET API to set timezone. Use reflection to assign time zone to the TimeZoneInfo.local field.
			FieldInfo localTimeZone = typeof(TimeZoneInfo).GetField("local", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
			localTimeZone.SetValue(null, tzInfo);

			DateTime st = new DateTime(2016, 3, 27, 1, 0, 0, DateTimeKind.Local);
			Assert.IsTrue (!tzInfo.IsDaylightSavingTime(st));	
			Assert.IsTrue (!tzInfo.IsAmbiguousTime(st));
			Assert.IsTrue ((TimeZoneInfo.ConvertTimeToUtc(st).Hour == 1));
			st = new DateTime(2016, 3, 27, 3, 0, 0, DateTimeKind.Local);
			Assert.IsTrue (tzInfo.IsDaylightSavingTime(st));	
			Assert.IsTrue (!tzInfo.IsAmbiguousTime(st));
			Assert.IsTrue ((TimeZoneInfo.ConvertTimeToUtc(st).Hour == 2));
			st = new DateTime(2016, 10, 30, 2, 0, 0, DateTimeKind.Local);
			Assert.IsTrue (!tzInfo.IsDaylightSavingTime(st));	
			Assert.IsTrue (tzInfo.IsAmbiguousTime(st));
304 305 306 307
			Assert.IsTrue ((TimeZoneInfo.ConvertTimeToUtc(st).Hour == 2));
			st = new DateTime(2016, 10, 30, 3, 0, 0, DateTimeKind.Local);
			Assert.IsTrue (!tzInfo.IsDaylightSavingTime(st));	
			Assert.IsTrue (!tzInfo.IsAmbiguousTime(st));
308 309 310 311 312 313 314
			Assert.IsTrue ((TimeZoneInfo.ConvertTimeToUtc(st).Hour == 3));
			st = new DateTime(2016, 10, 30, 4, 0, 0, DateTimeKind.Local);
			Assert.IsTrue (!tzInfo.IsDaylightSavingTime(st));	
			Assert.IsTrue (!tzInfo.IsAmbiguousTime(st));
			Assert.IsTrue ((TimeZoneInfo.ConvertTimeToUtc(st).Hour == 4));
		}

315
		[Test]
316
		[Category ("NotWorkingRuntimeInterpreter")]
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
		public void GetUtcOffsetAtDSTBoundary ()
		{
			/*
			 * Getting a definitive list of timezones which do or don't observe Daylight
			 * Savings is difficult (can't say America's or USA definitively) and lengthy see 
			 *
			 * http://en.wikipedia.org/wiki/Daylight_saving_time_by_country
			 *
			 * as a good starting point for a list.
			 *
			 * The following are SOME of the timezones/regions which do support daylight savings.
			 *
			 * Pacific/Auckland
			 * Pacific/Sydney
			 * USA (EST, CST, MST, PST, AKST) note this does not cover all states or regions
			 * Europe/London (GMT)
			 * CET (member states of the European Union)
			 *
			 * This test should work in all the above timezones
			 */


			TimeZone tz = TimeZone.CurrentTimeZone;
340 341
			int year = DateTime.Now.Year;
			DaylightTime daylightChanges = tz.GetDaylightChanges(year);
342 343 344
			DateTime dst_end = daylightChanges.End;

			if (dst_end == DateTime.MinValue)
345
				Assert.Ignore (tz.StandardName + " did not observe daylight saving time during " + year + ".");
346 347

			var standardOffset = tz.GetUtcOffset(daylightChanges.Start.AddMinutes(-1));
348
			var dstOffset = tz.GetUtcOffset(daylightChanges.Start.AddMinutes(61));
349

350
//			Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end));
351 352
			Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add (daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(1)))));
			Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ())));
353
			Assert.AreEqual(dstOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(-1)))));
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
			
			// This test assumes that the DST end is a "fall back" where we go to an earlier local time
			if (daylightChanges.Delta > TimeSpan.Zero)
			{
				// dst_end is the end time of the DST in DST time.
				// It is technically an ambiguous time because the same local time occurs twice, 
				// once in DST and then again in standard time
				// The ToUniversalTime() will assume standard time for ambiguous times, so we subtract
				// the DST delta to the the UTC time corresponding to the end of DST. Then
				// the ToLocalTime() will encode some extra info letting the framework know that we
				// are dealing with the ambiguous local time that is in DST.
				var dst_ambiguous = tz.ToUniversalTime(dst_end.Add(daylightChanges.Delta.Negate())).ToUniversalTime()
					.Add(daylightChanges.Delta.Negate()).ToLocalTime();

				Assert.AreEqual(dstOffset, tz.GetUtcOffset(dst_ambiguous));

				// The IsAmbiguousDaylightSavingTime flag is not cleared by DateTime.Add
				Assert.AreEqual(standardOffset, tz.GetUtcOffset(dst_ambiguous.Add(daylightChanges.Delta)));
				Assert.AreEqual(dstOffset, tz.GetUtcOffset(dst_ambiguous.Add(daylightChanges.Delta).Subtract(daylightChanges.Delta)));
			}
374 375 376
		}


M
Marek Safar 已提交
377 378 379 380 381 382 383 384 385 386
		[Test]
		public void StaticProperties ()
		{
			Assert.IsNotNull (TimeZoneInfo.Local, "Local");
			Assert.IsNotNull (TimeZoneInfo.Utc, "Utc");
		}
		
		[Test]
		public void FindSystemTimeZoneById ()
		{
387 388 389
			TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (TimeZoneInfoTest.MapTimeZoneId ("Canada/Eastern"));
			Assert.IsTrue ("EDT" == tzi.DaylightName || "Eastern Daylight Time" == tzi.DaylightName, "DaylightName");
			Assert.IsTrue ("EST" == tzi.StandardName || "Eastern Standard Time" == tzi.StandardName, "StandardName");
M
Marek Safar 已提交
390 391 392
			Assert.IsTrue (tzi.SupportsDaylightSavingTime, "SupportsDaylightSavingTime");
		}

393 394 395 396 397 398 399 400 401 402
		[Test]
		public void OldEraToLocalTime ()
		{
			TimeSpan offset = TimeSpan.Zero;
			var dto = new DateTimeOffset (new DateTime (1900, 1, 1).Ticks, offset);

			// Should never throw
			dto.ToLocalTime ();
		}

403
#if !WIN_PLATFORM
M
Marek Safar 已提交
404 405 406 407 408 409 410 411 412
		// On device we cannot read the OS file system to look for /etc/localtime
		// and /usr/share/zoneinfo - so we must initialize the BCL TimeZoneInfo
		// from NSTimeZoneInfo. The tests here check the code paths between the
		// two types - if they break then TimeZoneInfo work work at all
		// ref: http://bugzilla.xamarin.com/show_bug.cgi?id=1790
		
		[Test]
		public void GetSystemTimeZones ()
		{
413
			Assert.That (TimeZoneInfo.GetSystemTimeZones ().Count, Is.GreaterThan (400), "GetSystemTimeZones");
M
Marek Safar 已提交
414 415 416
		}
#endif
	}
417
}