X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem%2FTimeZone.cs;h=1cfa2ee9bcc3ecc73cacc8acac49ad997e890cde;hb=d326ae2998c679e1e78897cfcb2d5fd4fbcf2c8d;hp=316e99ce44b45950e71ca0162b679ae5ad439fef;hpb=0b3c3126ea203240ba9864ab9082c44935f32f4f;p=mono.git diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs index 316e99ce44b..1cfa2ee9bcc 100644 --- a/mcs/class/corlib/System/TimeZone.cs +++ b/mcs/class/corlib/System/TimeZone.cs @@ -68,16 +68,16 @@ namespace System // Properties public static TimeZone CurrentTimeZone { get { - long now = DateTime.GetNow (); - TimeZone tz; + long now = DateTime.UtcNow.Ticks; + TimeZone tz = currentTimeZone; lock (tz_lock) { - if (currentTimeZone == null || Math.Abs (now - timezone_check) > TimeSpan.TicksPerMinute) { - currentTimeZone = new CurrentSystemTimeZone (now); + if (tz == null || Math.Abs (now - timezone_check) > TimeSpan.TicksPerMinute) { + tz = new CurrentSystemTimeZone (); timezone_check = now; + + currentTimeZone = tz; } - - tz = currentTimeZone; } return tz; @@ -140,22 +140,7 @@ namespace System return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Local); } - DateTime local = DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local); - DaylightTime dlt = GetDaylightChanges (time.Year); - if (dlt.Delta.Ticks == 0) - return DateTime.SpecifyKind (local, DateTimeKind.Local); - - // FIXME: check all of the combination of - // - basis: local-based or UTC-based - // - hemisphere: Northern or Southern - // - offset: positive or negative - - // PST should work fine here. - if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local) - return DateTime.SpecifyKind (local, DateTimeKind.Local); - - TimeSpan localOffset = GetUtcOffset (local); - return DateTime.SpecifyKind (time.Add (localOffset), DateTimeKind.Local); + return DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local); } public virtual DateTime ToUniversalTime (DateTime time) @@ -176,222 +161,54 @@ namespace System return DateTime.SpecifyKind (new DateTime (time.Ticks - offset.Ticks), DateTimeKind.Utc); } - // - // This routine returns the TimeDiff that would have to be - // added to "time" to turn it into a local time. This would - // be equivalent to call ToLocalTime. - // - // There is one important consideration: - // - // This information is only valid during the minute it - // was called. - // - // This only works with a real time, not one of the boundary - // cases like DateTime.MaxValue, so validation must be done - // before. - // - // This is intended to be used by DateTime.Now - // - // We use a minute, just to be conservative and cope with - // any potential time zones that might be defined in the future - // that might not nicely fit in hour or half-hour steps. - // - internal TimeSpan GetLocalTimeDiff (DateTime time) - { - return GetLocalTimeDiff (time, GetUtcOffset (time)); - } - - // - // This routine is intended to be called by GetLocalTimeDiff(DatetTime) - // or by ToLocalTime after validation has been performed - // - // time is the time to map, utc_offset is the utc_offset that - // has been computed for calling GetUtcOffset on time. - // - // When called by GetLocalTime, utc_offset is assumed to come - // from a time constructed by new DateTime (DateTime.GetNow ()), that - // is a valid time. - // - // When called by ToLocalTime ranges are checked before this is - // called. - // - internal TimeSpan GetLocalTimeDiff (DateTime time, TimeSpan utc_offset) + internal static void ClearCachedData () { - DaylightTime dlt = GetDaylightChanges (time.Year); - - if (dlt.Delta.Ticks == 0) - return utc_offset; - - DateTime local = time.Add (utc_offset); - if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local) - return utc_offset; - - if (local >= dlt.Start && dlt.Start.Add (dlt.Delta) > local) - return utc_offset - dlt.Delta; - - return GetUtcOffset (local); + currentTimeZone = null; } } [Serializable] - internal class CurrentSystemTimeZone : TimeZone, IDeserializationCallback { + internal class CurrentSystemTimeZone : TimeZone { - // Fields - private string m_standardName; - private string m_daylightName; - - // A yearwise cache of DaylightTime. - private Dictionary m_CachedDaylightChanges = new Dictionary (1); - - // the offset when daylightsaving is not on (in ticks) - private long m_ticksOffset; - - // the offset when daylightsaving is not on. - [NonSerialized] - private TimeSpan utcOffsetWithOutDLS; - - // the offset when daylightsaving is on. - [NonSerialized] - private TimeSpan utcOffsetWithDLS; - - internal enum TimeZoneData - { - DaylightSavingStartIdx, - DaylightSavingEndIdx, - UtcOffsetIdx, - AdditionalDaylightOffsetIdx - }; - - internal enum TimeZoneNames - { - StandardNameIdx, - DaylightNameIdx - }; - - // Internal method to get timezone data. - // data[0]: start of daylight saving time (in DateTime ticks). - // data[1]: end of daylight saving time (in DateTime ticks). - // data[2]: utcoffset (in TimeSpan ticks). - // data[3]: additional offset when daylight saving (in TimeSpan ticks). - // name[0]: name of this timezone when not daylight saving. - // name[1]: name of this timezone when daylight saving. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool GetTimeZoneData (int year, out Int64[] data, out string[] names); + readonly TimeZoneInfo LocalTimeZone; // Constructor internal CurrentSystemTimeZone () { + LocalTimeZone = TimeZoneInfo.Local; } - // - // Initialized by the constructor - // - static int this_year; - static DaylightTime this_year_dlt; - - // - // The "lnow" parameter must be the current time, I could have moved - // the code here, but I do not want to interfere with serialization - // which is why I kept the other constructor around - // - internal CurrentSystemTimeZone (long lnow) - { - Int64[] data; - string[] names; - - DateTime now = new DateTime (lnow); - if (!GetTimeZoneData (now.Year, out data, out names)) - throw new NotSupportedException (Locale.GetText ("Can't get timezone name.")); - - m_standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]); - m_daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]); - - m_ticksOffset = data[(int)TimeZoneData.UtcOffsetIdx]; - - DaylightTime dlt = GetDaylightTimeFromData (data); - m_CachedDaylightChanges.Add (now.Year, dlt); - OnDeserialization (dlt); - } - - // Properties public override string DaylightName { - get { return m_daylightName; } + get { + return LocalTimeZone.DaylightName; + } } public override string StandardName { - get { return m_standardName; } + get { + return LocalTimeZone.StandardName; + } } - // Methods - public override DaylightTime GetDaylightChanges (int year) + public override System.Globalization.DaylightTime GetDaylightChanges (int year) { - if (year < 1 || year > 9999) - throw new ArgumentOutOfRangeException ("year", year + - Locale.GetText (" is not in a range between 1 and 9999.")); - - // - // First we try the case for this year, very common, and is used - // by DateTime.Now (a popular call) indirectly. - // - if (year == this_year) - return this_year_dlt; - - lock (m_CachedDaylightChanges) { - DaylightTime dlt; - if (!m_CachedDaylightChanges.TryGetValue (year, out dlt)) { - Int64[] data; - string[] names; - - if (!GetTimeZoneData (year, out data, out names)) - throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + year)); - - dlt = GetDaylightTimeFromData (data); - m_CachedDaylightChanges.Add (year, dlt); - } - return dlt; - } + return LocalTimeZone.GetDaylightChanges (year); } - public override TimeSpan GetUtcOffset (DateTime time) + public override TimeSpan GetUtcOffset (DateTime dateTime) { - if (time.Kind == DateTimeKind.Utc) + if (dateTime.Kind == DateTimeKind.Utc) return TimeSpan.Zero; - if (IsDaylightSavingTime (time)) - return utcOffsetWithDLS; - - return utcOffsetWithOutDLS; + return LocalTimeZone.GetUtcOffset (dateTime); } - void IDeserializationCallback.OnDeserialization (object sender) + public override bool IsDaylightSavingTime (DateTime dateTime) { - OnDeserialization (null); - } - - private void OnDeserialization (DaylightTime dlt) - { - if (dlt == null) { - Int64[] data; - string[] names; - - this_year = DateTime.Now.Year; - if (!GetTimeZoneData (this_year, out data, out names)) - throw new ArgumentException (Locale.GetText ("Can't get timezone data for " + this_year)); - dlt = GetDaylightTimeFromData (data); - } else - this_year = dlt.Start.Year; - - utcOffsetWithOutDLS = new TimeSpan (m_ticksOffset); - utcOffsetWithDLS = new TimeSpan (m_ticksOffset + dlt.Delta.Ticks); - this_year_dlt = dlt; - } + if (dateTime.Kind == DateTimeKind.Utc) + return false; - private DaylightTime GetDaylightTimeFromData (long[] data) - { - return new DaylightTime (new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]), - new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]), - new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx])); + return LocalTimeZone.IsDaylightSavingTime (dateTime); } - } }