summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared/System/CurrentSystemTimeZone.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/shared/System/CurrentSystemTimeZone.cs')
-rw-r--r--src/mscorlib/shared/System/CurrentSystemTimeZone.cs199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/mscorlib/shared/System/CurrentSystemTimeZone.cs b/src/mscorlib/shared/System/CurrentSystemTimeZone.cs
new file mode 100644
index 0000000000..2d848397a9
--- /dev/null
+++ b/src/mscorlib/shared/System/CurrentSystemTimeZone.cs
@@ -0,0 +1,199 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+** This class represents the current system timezone. It is
+** the only meaningful implementation of the TimeZone class
+** available in this version.
+**
+** The only TimeZone that we support in version 1 is the
+** CurrentTimeZone as determined by the system timezone.
+**
+**
+============================================================*/
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+ [Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")]
+ [Serializable]
+ internal partial class CurrentSystemTimeZone : TimeZone
+ {
+ // Standard offset in ticks to the Universal time if
+ // no daylight saving is in used.
+ // E.g. the offset for PST (Pacific Standard time) should be -8 * 60 * 60 * 1000 * 10000.
+ // (1 millisecond = 10000 ticks)
+ private long m_ticksOffset;
+ private String m_standardName;
+ private String m_daylightName;
+
+ internal CurrentSystemTimeZone()
+ {
+ TimeZoneInfo local = TimeZoneInfo.Local;
+
+ m_ticksOffset = local.BaseUtcOffset.Ticks;
+ m_standardName = local.StandardName;
+ m_daylightName = local.DaylightName;
+ }
+
+ public override String StandardName
+ {
+ get
+ {
+ return m_standardName;
+ }
+ }
+
+ public override String DaylightName
+ {
+ get
+ {
+ return m_daylightName;
+ }
+ }
+
+ internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst)
+ {
+ // Get the daylight changes for the year of the specified time.
+ TimeSpan offset = new TimeSpan(m_ticksOffset);
+ DaylightTime daylightTime = GetDaylightChanges(time.Year);
+ isAmbiguousLocalDst = false;
+
+ if (daylightTime == null || daylightTime.Delta.Ticks == 0)
+ {
+ return offset.Ticks;
+ }
+
+ // The start and end times represent the range of universal times that are in DST for that year.
+ // Within that there is an ambiguous hour, usually right at the end, but at the beginning in
+ // the unusual case of a negative daylight savings delta.
+ DateTime startTime = daylightTime.Start - offset;
+ DateTime endTime = daylightTime.End - offset - daylightTime.Delta;
+ DateTime ambiguousStart;
+ DateTime ambiguousEnd;
+
+ if (daylightTime.Delta.Ticks > 0)
+ {
+ ambiguousStart = endTime - daylightTime.Delta;
+ ambiguousEnd = endTime;
+ }
+ else
+ {
+ ambiguousStart = startTime;
+ ambiguousEnd = startTime - daylightTime.Delta;
+ }
+
+ Boolean isDst = false;
+ if (startTime > endTime)
+ {
+ // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
+ // Note, the summer in the southern hemisphere begins late in the year.
+ isDst = (time < endTime || time >= startTime);
+ }
+ else
+ {
+ // In northern hemisphere, the daylight saving time starts in the middle of the year.
+ isDst = (time >= startTime && time < endTime);
+ }
+
+ if (isDst)
+ {
+ offset += daylightTime.Delta;
+
+ // See if the resulting local time becomes ambiguous. This must be captured here or the
+ // DateTime will not be able to round-trip back to UTC accurately.
+ if (time >= ambiguousStart && time < ambiguousEnd)
+ {
+ isAmbiguousLocalDst = true;
+ }
+ }
+ return offset.Ticks;
+ }
+
+ public override DateTime ToLocalTime(DateTime time)
+ {
+ if (time.Kind == DateTimeKind.Local)
+ {
+ return time;
+ }
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ long tick = time.Ticks + offset;
+ if (tick > DateTime.MaxTicks)
+ {
+ return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
+ }
+ if (tick < DateTime.MinTicks)
+ {
+ return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
+ }
+ return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+
+ public override DaylightTime GetDaylightChanges(int year)
+ {
+ if (year < 1 || year > 9999)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, 1, 9999));
+ }
+
+ return GetCachedDaylightChanges(year);
+ }
+
+ private static DaylightTime CreateDaylightChanges(int year)
+ {
+ DaylightTime currentDaylightChanges = null;
+
+ if (TimeZoneInfo.Local.SupportsDaylightSavingTime)
+ {
+ DateTime start;
+ DateTime end;
+ TimeSpan delta;
+
+ foreach (var rule in TimeZoneInfo.Local.GetAdjustmentRules())
+ {
+ if (rule.DateStart.Year <= year && rule.DateEnd.Year >= year && rule.DaylightDelta != TimeSpan.Zero)
+ {
+ start = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionStart);
+ end = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionEnd);
+ delta = rule.DaylightDelta;
+
+ currentDaylightChanges = new DaylightTime(start, end, delta);
+ break;
+ }
+ }
+ }
+
+ if (currentDaylightChanges == null)
+ {
+ currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero);
+ }
+
+ return currentDaylightChanges;
+ }
+
+ public override TimeSpan GetUtcOffset(DateTime time)
+ {
+ if (time.Kind == DateTimeKind.Utc)
+ {
+ return TimeSpan.Zero;
+ }
+ else
+ {
+ return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
+ }
+ }
+ } // class CurrentSystemTimeZone
+}