Click here to Skip to main content
15,892,005 members
Articles / Programming Languages / C#

A TimeZone Aware DateTime Implementation

Rate me:
Please Sign up or sign in to vote.
3.56/5 (10 votes)
24 Feb 2010CPOL6 min read 70.3K   466   37  
An implementation that wraps DateTime to allow for keeping track of TimeZone state
using System;
using NUnit.Framework;
using DateTimeZone;
using TimeZone=DateTimeZone.TimeZone;

namespace TestDateTimeZone
{
	/// <summary>
	/// Testing that local time converted to utc will be converted back to the same local time around DST changes for any time zone.
	/// </summary>
	[TestFixture]
	public class LocalToUtcToLocalTest
	{
		
		[Test]
		public void TestCetToUtcBackToCetAroundDstSummerChange()
		{
			DateTime lastSundayInMarchCet = DateUtil.GetLastSundayInMarch(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInMarchCet, TimeZones.CET, false);

			// Adding 4 hours to both cet and utc representing the same time in different time zones
			for(int i=1; i<5; i++)
			{
				LocalDateTime modifiedCet = beforeDst.AddHours(i);
				UtcDateTime modifiedUtc = beforeDst.ConvertToUTC().AddHours(i);
				//Console.WriteLine("From: "+modifiedCet +" To: "+modifiedUtc);
				Assert.AreEqual(modifiedUtc, modifiedCet.ConvertToUTC());
				LocalDateTime result = modifiedUtc.AsLocalDateTime().ConvertTo(TimeZones.CET);
				//Console.WriteLine("From: "+modifiedUtc + " To: " + result);
				Assert.AreEqual(modifiedCet, result);

				//Console.WriteLine("-------------------------------------");
			}
		}

		[Test]
		public void TestCetAroundDstWinterChange()
		{
			DateTime lastSundayInOctoberCet = DateUtil.GetLastSundayInOctober(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInOctoberCet.AddHours(-1), TimeZones.CET, true);

			// Adding 4 hours to both cet and utc representing the same time in different time zones
			for (int i = 2; i < 5; i++)
			{
				//Console.WriteLine("Before: " + beforeDst);
				LocalDateTime modifiedCet = beforeDst.AddHours(i);
				//Console.WriteLine("+" + i + "h: " + modifiedCet);
				
				//Console.WriteLine("-------------------------------------");
			}
		}

		[Test]
		public void TestCetAroundDstWinterChangeWithTimeSpan2h()
		{
			DateTime lastSundayInOctoberCet = DateUtil.GetLastSundayInOctober(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInOctoberCet.AddHours(-1), TimeZones.CET, true);

			//Console.WriteLine("Before: " + beforeDst);
			LocalDateTime modifiedCet = beforeDst.AddTimeSpan(new TimeSpan(2, 0, 0));
			//Console.WriteLine("+2h: " + modifiedCet);
			Assert.AreEqual(new LocalDateTime(2009, 10, 25, 1, 0, 0, TimeZones.CET, true), modifiedCet);
		}

		[Test]
		public void TestCetAroundDstWinterChangeWithTimeSpan3h()
		{
			DateTime lastSundayInOctoberCet = DateUtil.GetLastSundayInOctober(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInOctoberCet.AddHours(-1), TimeZones.CET, true);

			//Console.WriteLine("Before: " + beforeDst);
			LocalDateTime modifiedCet = beforeDst.AddTimeSpan(new TimeSpan(3, 0, 0));
			//Console.WriteLine("+3h: " + modifiedCet);
			Assert.AreEqual(new LocalDateTime(2009, 10, 25, 2, 0, 0, TimeZones.CET, true), modifiedCet);
		}

		[Test]
		public void TestCetAroundDstWinterChangeWithTimeSpan4hCausingFallback()
		{
			DateTime lastSundayInOctoberCet = DateUtil.GetLastSundayInOctober(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInOctoberCet.AddHours(-1), TimeZones.CET, true);

			//Console.WriteLine("Before: " + beforeDst);
			LocalDateTime modifiedCet = beforeDst.AddTimeSpan(new TimeSpan(4, 0, 0));
			//Console.WriteLine("+4h: " + modifiedCet);
			Assert.AreEqual(new LocalDateTime(2009, 10, 25, 2, 0, 0, TimeZones.CET, false), modifiedCet);
		}

		[Test]
		public void TestCetToUtcBackToCetAroundDstWinterChange()
		{
			DateTime lastSundayInOctoberCet = DateUtil.GetLastSundayInOctober(2009);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInOctoberCet.AddHours(-1), TimeZones.CET, true);

			// Adding 4 hours to both cet and utc representing the same time in different time zones
			for (int i = 1; i < 5; i++)
			{
				//Console.WriteLine("Before: " + beforeDst);
				//Console.WriteLine("Before: " + beforeDst.ConvertToUTC());
				//Console.WriteLine("--");
				LocalDateTime modifiedCet = beforeDst.AddHours(i);
				UtcDateTime modifiedUtc = beforeDst.ConvertToUTC().AddHours(i);
				//Console.WriteLine("+"+i+"h: " + modifiedCet);
				//Console.WriteLine("+" + i + "h: " + modifiedUtc);
				Assert.AreEqual(modifiedUtc, modifiedCet.ConvertToUTC());

				//Console.WriteLine("-------------------------------------");
			}
		}

		[Test]
		public void TestCetToUtcBackToCetAroundDstSummerChange01_59_59()
		{
			DateTime lastSundayInMarchCet = DateUtil.GetLastSundayInMarch(2009).AddHours(-1).AddMinutes(-1);
			LocalDateTime beforeDst = new LocalDateTime(lastSundayInMarchCet, TimeZones.CET, false);

			// Adding 4 hours to both cet and utc representing the same time in different time zones
			for (int i = 1; i < 5; i++)
			{
				LocalDateTime modifiedCet = beforeDst.AddHours(i);
				UtcDateTime modifiedUtc = beforeDst.ConvertToUTC().AddHours(i);
				//Console.WriteLine("From: " + modifiedCet + " To: " + modifiedUtc);
				Assert.AreEqual(modifiedUtc, modifiedCet.ConvertToUTC());
				LocalDateTime result = modifiedUtc.AsLocalDateTime().ConvertTo(TimeZones.CET);
				//Console.WriteLine("From: " + modifiedUtc + " To: " + result);
				Assert.AreEqual(modifiedCet, result);

				//Console.WriteLine("-------------------------------------");
			}
		}

		[Test]
		public void TestCetToUtcBackToNewYorkAroundDstSummerChange01_59_59()
		{
			TimeZone tz = TimeZones.America__New_York;
			DateTime beforeDstStart = tz.GetDSTStart(2009).AddHours(-1).AddMinutes(-1);
			LocalDateTime beforeDst = new LocalDateTime(beforeDstStart, tz, false);

			// Adding 4 hours to both cet and utc representing the same time in different time zones
			for (int i = 1; i < 5; i++)
			{
				LocalDateTime modifiedCet = beforeDst.AddHours(i);
				UtcDateTime modifiedUtc = beforeDst.ConvertToUTC().AddHours(i);
				//Console.WriteLine("From: " + modifiedCet + " To: " + modifiedUtc);
				Assert.AreEqual(modifiedUtc, modifiedCet.ConvertToUTC());
				LocalDateTime result = modifiedUtc.AsLocalDateTime().ConvertTo(tz);
				//Console.WriteLine("From: " + modifiedUtc + " To: " + result);
				Assert.AreEqual(modifiedCet, result);

				//Console.WriteLine("-------------------------------------");
			}


		}

		/// <summary>
		/// Testing that UTC time jut before winter change will find the correct 2 hour in CET
		/// In this test, the UTC time is 12am and should then be adjusten to 2am CET summer time.
		/// </summary>
		[Test]
		public void TestUtc_2510_2009_00_ToCet()
		{
			DateTime expected = new DateTime(2009, 10, 25, 2,0,0);
			UtcDateTime utc = new UtcDateTime(2009, 10, 25);
			TimeZone toTimeZone = TimeZones.CET;
			
			LocalDateTime local = utc.AsLocalDateTime().ConvertTo(toTimeZone);
			//Console.WriteLine(local);
			Assert.AreEqual(expected, local.GetDateTime());
		}

		/// <summary>
		/// Testing that UTC time jut before winter change will find the correct 2 hour in CET
		/// In this test, the UTC time is 1am and should then be adjusten to 2am CET winter time.
		/// </summary>
		[Test]
		public void TestUtc_2510_2009_01_ToCet()
		{
			DateTime expected = new DateTime(2009, 10, 25, 2, 0, 0);
			UtcDateTime utc = new UtcDateTime(2009, 10, 25, 1,0,0);
			TimeZone toTimeZone = TimeZones.CET;

			LocalDateTime local = utc.AsLocalDateTime().ConvertTo(toTimeZone);
			//Console.WriteLine(local);
			Assert.AreEqual(expected, local.GetDateTime());
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Norway Norway
http://www.linkedin.com/in/steinardragsnes

Comments and Discussions