4 // Author: Duncan Mak (duncan@ximian.com)
5 // Ajay Kumar Dwivedi (adwiv@yahoo.com)
6 // Martin Baulig (martin@gnome.org)
11 using System.Collections;
12 using System.Globalization;
13 using System.Runtime.CompilerServices;
18 public abstract class TimeZone
21 private static TimeZone currentTimeZone;
29 public static TimeZone CurrentTimeZone
32 if (currentTimeZone == null)
33 currentTimeZone = new CurrentTimeZone ();
35 return currentTimeZone;
39 public abstract string DaylightName
44 public abstract string StandardName
50 public abstract DaylightTime GetDaylightChanges (int year);
52 public abstract TimeSpan GetUtcOffset (DateTime time);
54 public virtual bool IsDaylightSavingTime (DateTime time)
56 return IsDaylightSavingTime (time, GetDaylightChanges (time.Year));
59 public static bool IsDaylightSavingTime (DateTime time, DaylightTime daylightTimes)
61 if (daylightTimes == null)
62 throw new ArgumentNullException ("daylightTimes");
64 // If Start == End, then DST is off
65 if (daylightTimes.Start.Ticks == daylightTimes.End.Ticks)
68 //We are in the northern hemisphere.
69 if (daylightTimes.Start.Ticks < daylightTimes.End.Ticks) {
70 if (daylightTimes.Start.Ticks < time.Ticks
71 && daylightTimes.End.Ticks > time.Ticks)
72 return true; // time lies between Start and End
74 } else { // We are in the southern hemisphere.
75 if (time.Year == daylightTimes.Start.Year && time.Year == daylightTimes.End.Year)
76 if (time.Ticks < daylightTimes.End.Ticks
77 || time.Ticks > daylightTimes.Start.Ticks)
78 return true; // time is less than End OR more than Start
84 public virtual DateTime ToLocalTime (DateTime time)
86 return time + GetUtcOffset (time);
89 public virtual DateTime ToUniversalTime (DateTime time)
91 return time - GetUtcOffset (time);
95 internal class CurrentTimeZone : TimeZone
98 private static string daylightName;
99 private static string standardName;
101 // A yearwise cache of DaylightTime.
102 private static Hashtable daylightCache = new Hashtable (1);
104 // the offset when daylightsaving is not on.
105 private static TimeSpan utcOffsetWithOutDLS;
107 // the offset when daylightsaving is on.
108 private static TimeSpan utcOffsetWithDLS;
110 internal enum TimeZoneData {
111 DaylightSavingStartIdx,
112 DaylightSavingEndIdx,
114 AdditionalDaylightOffsetIdx
117 internal enum TimeZoneNames {
122 // Internal method to get timezone data.
123 // data[0]: start of daylight saving time (in DateTime ticks).
124 // data[1]: end of daylight saving time (in DateTime ticks).
125 // data[2]: utcoffset (in TimeSpan ticks).
126 // data[3]: additional offset when daylight saving (in TimeSpan ticks).
127 // name[0]: name of this timezone when not daylight saving.
128 // name[1]: name of this timezone when daylight saving.
129 [MethodImplAttribute(MethodImplOptions.InternalCall)]
130 private static extern bool GetTimeZoneData (int year,
135 internal CurrentTimeZone ()
141 DateTime now = new DateTime(DateTime.GetNow ());
142 if (!GetTimeZoneData (now.Year, out data, out names))
143 throw new NotSupportedException (Locale.GetText ("Can't get timezone name"));
145 standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
146 daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
148 utcOffsetWithOutDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]);
149 utcOffsetWithDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx] + data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]);
153 public override string DaylightName
155 get { return daylightName; }
158 public override string StandardName
160 get { return standardName; }
165 public override DaylightTime GetDaylightChanges (int year)
167 if (year < 1 || year > 9999)
168 throw new ArgumentOutOfRangeException (year + " is not in a range between 1 and 9999.");
170 if (daylightCache [year] == null) {
172 if (daylightCache [year] == null) {
176 if (!GetTimeZoneData (year, out data, out names))
177 throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + year));
179 DaylightTime dlt = new DaylightTime (new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]),
180 new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]),
181 new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]));
182 daylightCache.Add (year, dlt);
187 return (DaylightTime) daylightCache [year];
190 public override TimeSpan GetUtcOffset (DateTime time)
192 if (IsDaylightSavingTime (time))
193 return utcOffsetWithDLS;
195 return utcOffsetWithOutDLS;