5 // Duncan Mak (duncan@ximian.com)
6 // Ajay Kumar Dwivedi (adwiv@yahoo.com)
7 // Martin Baulig (martin@gnome.org)
12 using System.Collections;
13 using System.Globalization;
14 using System.Runtime.CompilerServices;
19 public abstract class TimeZone
22 private static TimeZone currentTimeZone;
30 public static TimeZone CurrentTimeZone {
32 if (currentTimeZone == null)
33 currentTimeZone = new CurrentTimeZone ();
35 return currentTimeZone;
39 public abstract string DaylightName {
43 public abstract string StandardName {
48 public abstract DaylightTime GetDaylightChanges (int year);
50 public abstract TimeSpan GetUtcOffset (DateTime time);
52 public virtual bool IsDaylightSavingTime (DateTime time)
54 return IsDaylightSavingTime (time, GetDaylightChanges (time.Year));
57 public static bool IsDaylightSavingTime (DateTime time, DaylightTime daylightTimes)
59 if (daylightTimes == null)
60 throw new ArgumentNullException ("daylightTimes");
62 // If Start == End, then DST is off
63 if (daylightTimes.Start.Ticks == daylightTimes.End.Ticks)
66 //We are in the northern hemisphere.
67 if (daylightTimes.Start.Ticks < daylightTimes.End.Ticks) {
68 if (daylightTimes.Start.Ticks < time.Ticks && daylightTimes.End.Ticks > time.Ticks)
69 return true; // time lies between Start and End
72 else { // We are in the southern hemisphere.
73 if (time.Year == daylightTimes.Start.Year && time.Year == daylightTimes.End.Year)
74 if (time.Ticks < daylightTimes.End.Ticks || time.Ticks > daylightTimes.Start.Ticks)
75 return true; // time is less than End OR more than Start
81 public virtual DateTime ToLocalTime (DateTime time)
83 return time + GetUtcOffset (time);
86 public virtual DateTime ToUniversalTime (DateTime time)
88 return time - GetUtcOffset (time);
92 internal class CurrentTimeZone : TimeZone
95 private static string daylightName;
96 private static string standardName;
98 // A yearwise cache of DaylightTime.
99 private static Hashtable daylightCache = new Hashtable (1);
101 // the offset when daylightsaving is not on.
102 private static TimeSpan utcOffsetWithOutDLS;
104 // the offset when daylightsaving is on.
105 private static TimeSpan utcOffsetWithDLS;
107 internal enum TimeZoneData
109 DaylightSavingStartIdx,
110 DaylightSavingEndIdx,
112 AdditionalDaylightOffsetIdx
115 internal enum TimeZoneNames
121 // Internal method to get timezone data.
122 // data[0]: start of daylight saving time (in DateTime ticks).
123 // data[1]: end of daylight saving time (in DateTime ticks).
124 // data[2]: utcoffset (in TimeSpan ticks).
125 // data[3]: additional offset when daylight saving (in TimeSpan ticks).
126 // name[0]: name of this timezone when not daylight saving.
127 // name[1]: name of this timezone when daylight saving.
128 [MethodImplAttribute(MethodImplOptions.InternalCall)]
129 private static extern bool GetTimeZoneData (int year, out Int64[] data, out string[] names);
132 internal CurrentTimeZone ()
138 DateTime now = new DateTime(DateTime.GetNow ());
139 if (!GetTimeZoneData (now.Year, out data, out names))
140 throw new NotSupportedException (Locale.GetText ("Can't get timezone name."));
142 standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
143 daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
145 utcOffsetWithOutDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]);
146 utcOffsetWithDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]
147 + data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]);
151 public override string DaylightName {
152 get { return daylightName; }
155 public override string StandardName {
156 get { return standardName; }
161 public override DaylightTime GetDaylightChanges (int year)
163 if (year < 1 || year > 9999)
164 throw new ArgumentOutOfRangeException ("year", year +
165 Locale.GetText (" is not in a range between 1 and 9999."));
167 if (daylightCache [year] == null) {
169 if (daylightCache [year] == null) {
173 if (!GetTimeZoneData (year, out data, out names))
174 throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + year));
176 DaylightTime dlt = new DaylightTime (new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]),
177 new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]),
178 new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]));
179 daylightCache.Add (year, dlt);
184 return (DaylightTime) daylightCache [year];
187 public override TimeSpan GetUtcOffset (DateTime time)
189 if (IsDaylightSavingTime (time))
190 return utcOffsetWithDLS;
192 return utcOffsetWithOutDLS;