**** Merged from MCS ****
[mono-project.git] / mcs / class / corlib / System / TimeZone.cs
blob8031be95943288d7081de0cf8d72ffa0e5c062bf
1 //
2 // System.TimeZone.cs
3 //
4 // Authors:
5 // Duncan Mak (duncan@ximian.com)
6 // Ajay Kumar Dwivedi (adwiv@yahoo.com)
7 // Martin Baulig (martin@gnome.org)
8 //
9 // (C) Ximian, Inc.
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections;
36 using System.Globalization;
37 using System.Runtime.CompilerServices;
39 namespace System
41 [Serializable]
42 public abstract class TimeZone
44 // Fields
45 private static TimeZone currentTimeZone;
47 // Constructor
48 protected TimeZone ()
52 // Properties
53 public static TimeZone CurrentTimeZone {
54 get {
55 if (currentTimeZone == null)
56 currentTimeZone = new CurrentTimeZone ();
58 return currentTimeZone;
62 public abstract string DaylightName {
63 get;
66 public abstract string StandardName {
67 get;
70 // Methods
71 public abstract DaylightTime GetDaylightChanges (int year);
73 public abstract TimeSpan GetUtcOffset (DateTime time);
75 public virtual bool IsDaylightSavingTime (DateTime time)
77 return IsDaylightSavingTime (time, GetDaylightChanges (time.Year));
80 public static bool IsDaylightSavingTime (DateTime time, DaylightTime daylightTimes)
82 if (daylightTimes == null)
83 throw new ArgumentNullException ("daylightTimes");
85 // If Start == End, then DST is off
86 if (daylightTimes.Start.Ticks == daylightTimes.End.Ticks)
87 return false;
89 //We are in the northern hemisphere.
90 if (daylightTimes.Start.Ticks < daylightTimes.End.Ticks) {
91 if (daylightTimes.Start.Ticks < time.Ticks && daylightTimes.End.Ticks > time.Ticks)
92 return true; // time lies between Start and End
95 else { // We are in the southern hemisphere.
96 if (time.Year == daylightTimes.Start.Year && time.Year == daylightTimes.End.Year)
97 if (time.Ticks < daylightTimes.End.Ticks || time.Ticks > daylightTimes.Start.Ticks)
98 return true; // time is less than End OR more than Start
101 return false;
104 public virtual DateTime ToLocalTime (DateTime time)
106 return time + GetUtcOffset (time);
109 public virtual DateTime ToUniversalTime (DateTime time)
111 return time - GetUtcOffset (time);
115 internal class CurrentTimeZone : TimeZone
117 // Fields
118 private static string daylightName;
119 private static string standardName;
121 // A yearwise cache of DaylightTime.
122 private static Hashtable daylightCache = new Hashtable (1);
124 // the offset when daylightsaving is not on.
125 private static TimeSpan utcOffsetWithOutDLS;
127 // the offset when daylightsaving is on.
128 private static TimeSpan utcOffsetWithDLS;
130 internal enum TimeZoneData
132 DaylightSavingStartIdx,
133 DaylightSavingEndIdx,
134 UtcOffsetIdx,
135 AdditionalDaylightOffsetIdx
138 internal enum TimeZoneNames
140 StandardNameIdx,
141 DaylightNameIdx
144 // Internal method to get timezone data.
145 // data[0]: start of daylight saving time (in DateTime ticks).
146 // data[1]: end of daylight saving time (in DateTime ticks).
147 // data[2]: utcoffset (in TimeSpan ticks).
148 // data[3]: additional offset when daylight saving (in TimeSpan ticks).
149 // name[0]: name of this timezone when not daylight saving.
150 // name[1]: name of this timezone when daylight saving.
151 [MethodImplAttribute(MethodImplOptions.InternalCall)]
152 private static extern bool GetTimeZoneData (int year, out Int64[] data, out string[] names);
154 // Constructor
155 internal CurrentTimeZone ()
156 : base ()
158 Int64[] data;
159 string[] names;
161 DateTime now = new DateTime(DateTime.GetNow ());
162 if (!GetTimeZoneData (now.Year, out data, out names))
163 throw new NotSupportedException (Locale.GetText ("Can't get timezone name."));
165 standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
166 daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
168 utcOffsetWithOutDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]);
169 utcOffsetWithDLS = new TimeSpan (data[(int)TimeZoneData.UtcOffsetIdx]
170 + data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]);
173 // Properties
174 public override string DaylightName {
175 get { return daylightName; }
178 public override string StandardName {
179 get { return standardName; }
182 // Methods
183 [MonoTODO]
184 public override DaylightTime GetDaylightChanges (int year)
186 if (year < 1 || year > 9999)
187 throw new ArgumentOutOfRangeException ("year", year +
188 Locale.GetText (" is not in a range between 1 and 9999."));
190 if (daylightCache [year] == null) {
191 lock (this) {
192 if (daylightCache [year] == null) {
193 Int64[] data;
194 string[] names;
196 if (!GetTimeZoneData (year, out data, out names))
197 throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + year));
199 DaylightTime dlt = new DaylightTime (new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]),
200 new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]),
201 new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]));
202 daylightCache.Add (year, dlt);
207 return (DaylightTime) daylightCache [year];
210 public override TimeSpan GetUtcOffset (DateTime time)
212 if (IsDaylightSavingTime (time))
213 return utcOffsetWithDLS;
215 return utcOffsetWithOutDLS;