Prepare TimeZoneInfo.cs for move to shared partition. (dotnet/coreclr#10606)
authorAtsushi Kanamori <AtsushiKan@users.noreply.github.com>
Fri, 31 Mar 2017 14:20:30 +0000 (07:20 -0700)
committerGitHub <noreply@github.com>
Fri, 31 Mar 2017 14:20:30 +0000 (07:20 -0700)
(This is the CoreRT side of https://github.com/dotnet/coreclr/pull/10606)

TimeZoneInfo.cs needs no changes but it brings in
another file CurrentTimeZone.cs.

Which drags in yet another file (Hashtable.cs)
which is widely used inside CoreCLR but aside
from this one file, it seems to be stuff that'll
will never be ported over or already has been
ported over sans Hashtable.

So we'll refactor the memoization logic of
CurrentTimeZone.cs into its own partial file
and share the rest. CoreCLR will use continue to use Hashtable.
CoreRT will use ConcurrentUnifier.

And while we're at it, will rename it to
CurrentSystemTimeZone.cs to match the actual class name.

Once we make a corresponding change on the CoreCLR side,
both TimeZone.cs and CurrentSystemTimeZone.cs will
be fully synced and can move to the shared partition.

Commit migrated from https://github.com/dotnet/coreclr/commit/47931672c057514cac0db20534cee6fe89eb8027

src/coreclr/src/mscorlib/System.Private.CoreLib.csproj
src/coreclr/src/mscorlib/src/System/CurrentSystemTimeZone.Cache.cs [new file with mode: 0644]
src/coreclr/src/mscorlib/src/System/CurrentSystemTimeZone.cs [moved from src/coreclr/src/mscorlib/src/System/CurrentTimeZone.cs with 75% similarity]

index 6f18a4f..489bda3 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.CoreClrOverrides.cs" />
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.cs" />
     <Compile Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.Central.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\CurrentTimeZone.cs" />
+    <Compile Include="$(BclSourcesRoot)\System\CurrentSystemTimeZone.cs" />
+    <Compile Include="$(BclSourcesRoot)\System\CurrentSystemTimeZone.Cache.cs" />
     <Compile Include="$(BclSourcesRoot)\System\TimeZone.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Object.cs" />
     <Compile Include="$(BclSourcesRoot)\System\ICloneable.cs" />
diff --git a/src/coreclr/src/mscorlib/src/System/CurrentSystemTimeZone.Cache.cs b/src/coreclr/src/mscorlib/src/System/CurrentSystemTimeZone.Cache.cs
new file mode 100644 (file)
index 0000000..744c697
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+using System.Collections;
+using System.Globalization;
+
+namespace System
+{
+    internal partial class CurrentSystemTimeZone
+    {
+        private DaylightTime GetCachedDaylightChanges(int year)
+        {
+            Object objYear = (Object)year;
+
+            if (!m_CachedDaylightChanges.Contains(objYear))
+            {
+                DaylightTime currentDaylightChanges = CreateDaylightChanges(year);
+                lock (m_CachedDaylightChanges)
+                {
+                    if (!m_CachedDaylightChanges.Contains(objYear))
+                    {
+                        m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+                    }
+                }
+            }
+
+            return (DaylightTime)m_CachedDaylightChanges[objYear];
+        }
+
+        // The per-year information is cached in in this instance value. As a result it can
+        // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
+        private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
+    }
+}
@@ -29,12 +29,8 @@ namespace System
 {
     [Obsolete("System.CurrentSystemTimeZone has been deprecated.  Please investigate the use of System.TimeZoneInfo.Local instead.")]
     [Serializable]
-    internal class CurrentSystemTimeZone : TimeZone
+    internal partial class CurrentSystemTimeZone : TimeZone
     {
-        // The per-year information is cached in in this instance value. As a result it can
-        // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
-        private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
-
         // 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.
@@ -152,51 +148,40 @@ namespace System
             {
                 throw new ArgumentOutOfRangeException(nameof(year), SR.Format(SR.ArgumentOutOfRange_Range, 1, 9999));
             }
-            Contract.EndContractBlock();
 
-            Object objYear = (Object)year;
+            return GetCachedDaylightChanges(year);
+        }
+
+        private static DaylightTime CreateDaylightChanges(int year)
+        {
+            DaylightTime currentDaylightChanges = null;
 
-            if (!m_CachedDaylightChanges.Contains(objYear))
+            if (TimeZoneInfo.Local.SupportsDaylightSavingTime)
             {
-                DaylightTime currentDaylightChanges = null;
+                DateTime start;
+                DateTime end;
+                TimeSpan delta;
 
-                if (TimeZoneInfo.Local.SupportsDaylightSavingTime)
+                foreach (var rule in TimeZoneInfo.Local.GetAdjustmentRules())
                 {
-                    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)
                     {
-                        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;
-                        }
-                    }
-                }
+                        start = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionStart);
+                        end = TimeZoneInfo.TransitionTimeToDateTime(year, rule.DaylightTransitionEnd);
+                        delta = rule.DaylightDelta;
 
-                if (currentDaylightChanges == null)
-                {
-                    currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero);
-                }
-
-                lock (m_CachedDaylightChanges)
-                {
-                    if (!m_CachedDaylightChanges.Contains(objYear))
-                    {
-                        m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+                        currentDaylightChanges = new DaylightTime(start, end, delta);
+                        break;
                     }
                 }
             }
 
-            DaylightTime result = (DaylightTime)m_CachedDaylightChanges[objYear];
+            if (currentDaylightChanges == null)
+            {
+                currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero);
+            }
 
-            return result;
+            return currentDaylightChanges;
         }
 
         public override TimeSpan GetUtcOffset(DateTime time)