Enable time zone for netstandard1.7 (#8074)
authorTarek Mahmoud Sayed <tarekms@microsoft.com>
Fri, 11 Nov 2016 00:58:28 +0000 (16:58 -0800)
committerGitHub <noreply@github.com>
Fri, 11 Nov 2016 00:58:28 +0000 (16:58 -0800)
* Expose and reimplement TimeZone class

The change is exposing the missing TimeZone APIs from corelib so can be useded in netstandard 1.7.
The change here is re-implementing CurrentTimeZone class to be simpler and also to make it work for Linux platforms. we used TimeZoneInfo class to reimplement it and also cleaned up all used internal calls as not needed anymore.

* Small delta fix

* Fix the code according to the review comments

src/classlibnative/inc/nlsinfo.h
src/classlibnative/nls/nlsinfo.cpp
src/mscorlib/model.xml
src/mscorlib/src/System/CurrentTimeZone.cs
src/mscorlib/src/System/TimeZoneInfo.cs
src/vm/ecalllist.h

index 4b7a036..a5dc13f 100644 (file)
@@ -118,17 +118,6 @@ public:
 #endif
     static BOOL QCALLTYPE InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation);
 
-
-#ifndef FEATURE_CORECLR
-    //
-    //  Native helper function for methods in TimeZone
-    //
-    static FCDECL0(LONG, nativeGetTimeZoneMinuteOffset);
-    static FCDECL0(Object*, nativeGetStandardName);
-    static FCDECL0(Object*, nativeGetDaylightName);
-    static FCDECL1(Object*, nativeGetDaylightChanges, int year);
-#endif // FEATURE_CORECLR
-
     //
     //  Native helper function for methods in EncodingTable
     //
index b930673..0e034c4 100644 (file)
@@ -1877,127 +1877,6 @@ INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, INT_PT
     return(iReturnHash);
 }
 
-#ifndef FEATURE_CORECLR // FCalls used by System.TimeZone
-
-FCIMPL0(LONG, COMNlsInfo::nativeGetTimeZoneMinuteOffset)
-{
-    FCALL_CONTRACT;
-
-    TIME_ZONE_INFORMATION timeZoneInfo;
-
-    GetTimeZoneInformation(&timeZoneInfo);
-
-    //
-    // In Win32, UTC = local + offset.  So for Pacific Standard Time, offset = 8.
-    // In NLS+, Local time = UTC + offset. So for PST, offset = -8.
-    // So we have to reverse the sign here.
-    //
-    return (timeZoneInfo.Bias * -1);
-}
-FCIMPLEND
-
-FCIMPL0(Object*, COMNlsInfo::nativeGetStandardName)
-{
-    FCALL_CONTRACT;
-
-    STRINGREF refRetVal = NULL;
-    HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
-
-    TIME_ZONE_INFORMATION timeZoneInfo;
-    GetTimeZoneInformation(&timeZoneInfo);
-
-    refRetVal = StringObject::NewString(timeZoneInfo.StandardName);
-
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(refRetVal);
-}
-FCIMPLEND
-
-FCIMPL0(Object*, COMNlsInfo::nativeGetDaylightName)
-{
-    FCALL_CONTRACT;
-
-    STRINGREF refRetVal = NULL;
-    HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
-
-    TIME_ZONE_INFORMATION timeZoneInfo;
-    GetTimeZoneInformation(&timeZoneInfo);
-    // Instead of returning null when daylight saving is not used, now we return the same result as the OS.
-    //In this case, if daylight saving time is used, the standard name is returned.
-
-#if 0
-    if (result == TIME_ZONE_ID_UNKNOWN || timeZoneInfo.DaylightDate.wMonth == 0) {
-        // If daylight saving time is not used in this timezone, return null.
-        //
-        // Windows NT/2000: TIME_ZONE_ID_UNKNOWN is returned if daylight saving time is not used in
-        // the current time zone, because there are no transition dates.
-        //
-        // For Windows 9x, a zero in the wMonth in DaylightDate means daylight saving time
-        // is not specified.
-        //
-        // If the current timezone uses daylight saving rule, but user unchekced the
-        // "Automatically adjust clock for daylight saving changes", the value
-        // for DaylightBias will be 0.
-        return (I2ARRAYREF)NULL;
-    }
-#endif  // 0
-
-    refRetVal = StringObject::NewString(timeZoneInfo.DaylightName);
-
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(refRetVal);
-}
-FCIMPLEND
-
-FCIMPL1(Object*, COMNlsInfo::nativeGetDaylightChanges, int year)
-{
-    FCALL_CONTRACT;
-
-    I2ARRAYREF pResultArray = NULL;
-    HELPER_METHOD_FRAME_BEGIN_RET_1(pResultArray);
-
-    TIME_ZONE_INFORMATION timeZoneInfo;
-    DWORD result = GetTimeZoneInformation(&timeZoneInfo);
-
-    if (result == TIME_ZONE_ID_UNKNOWN || timeZoneInfo.DaylightBias == 0
-        || timeZoneInfo.DaylightDate.wMonth == 0
-        ) {
-        // If daylight saving time is not used in this timezone, return null.
-        //
-        // If the current timezone uses daylight saving rule, but user unchekced the
-        // "Automatically adjust clock for daylight saving changes", the value
-        // for DaylightBias will be 0.
-        goto lExit;
-    }
-
-    pResultArray = (I2ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_I2, 17);
-
-    //
-    // The content of timeZoneInfo.StandardDate is 8 words, which
-    // contains year, month, day, dayOfWeek, hour, minute, second, millisecond.
-    //
-    memcpyNoGCRefs(pResultArray->m_Array,
-            (LPVOID)&timeZoneInfo.DaylightDate,
-            8 * sizeof(INT16));
-
-    //
-    // The content of timeZoneInfo.DaylightDate is 8 words, which
-    // contains year, month, day, dayOfWeek, hour, minute, second, millisecond.
-    //
-    memcpyNoGCRefs(((INT16*)pResultArray->m_Array) + 8,
-            (LPVOID)&timeZoneInfo.StandardDate,
-            8 * sizeof(INT16));
-
-    ((INT16*)pResultArray->m_Array)[16] = (INT16)timeZoneInfo.DaylightBias * -1;
-
-lExit: ;
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(pResultArray);
-}
-FCIMPLEND
-
-#endif // FEATURE_CORECLR
-
 inline BOOL IsInvariantLocale(STRINGREF localeName)
 {
    return localeName->GetStringLength() == 0;
index 5fb44e8..8d8ff11 100644 (file)
     </Type>
     <Type Name="System.TimeZone">
       <Member Name="#ctor" />
+      <Member Name="get_CurrentTimeZone" />
       <Member Name="get_DaylightName" />
       <Member Name="get_StandardName" />
       <Member Name="GetDaylightChanges(System.Int32)" />
       <Member Name="GetUtcOffset(System.DateTime)" />
       <Member Name="IsDaylightSavingTime(System.DateTime)" />
       <Member Name="IsDaylightSavingTime(System.DateTime,System.Globalization.DaylightTime)" />
+      <Member Name="ToLocalTime(System.DateTime)" />
       <Member Name="ToUniversalTime(System.DateTime)" />
+      <Member MemberType="Property" Name="CurrentTimeZone" />
       <Member MemberType="Property" Name="DaylightName" />
       <Member MemberType="Property" Name="StandardName" />
-<!-- This members need CurrentSystemTimeZone which needs Linux implementations
-      <Member Name="ToLocalTime(System.DateTime)" />
-      <Member MemberType="Property" Name="CurrentTimeZone" />
-      <Member Name="get_CurrentTimeZone" />
--->
     </Type>
     <Type Name="System.TimeZoneInfo">
       <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
index 59decb5..f98117b 100644 (file)
@@ -27,27 +27,12 @@ namespace System {
     using System.Runtime.CompilerServices;
     using System.Runtime.Versioning;
 
-    //
-    // Currently, this is the only supported timezone.
-    // The values of the timezone is from the current system timezone setting in the
-    // control panel.
-    //
 #if FEATURE_CORECLR
     [Obsolete("System.CurrentSystemTimeZone has been deprecated.  Please investigate the use of System.TimeZoneInfo.Local instead.")]
 #endif
     [Serializable]
-    internal class CurrentSystemTimeZone : TimeZone {
-        // <BUGBUG>BUGBUG :
-        // One problem is when user changes the current timezone.  We 
-        // are not able to update currentStandardName/currentDaylightName/
-        // currentDaylightChanges.
-        // We need WM_TIMECHANGE to do this or use
-        // RegNotifyChangeKeyValue() to monitor </BUGBUG>
-        //    
-        private const long TicksPerMillisecond = 10000;
-        private const long TicksPerSecond = TicksPerMillisecond * 1000;
-        private const long TicksPerMinute = TicksPerSecond * 60;
-
+    internal 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 Hashtable m_CachedDaylightChanges = new Hashtable();
@@ -60,43 +45,40 @@ namespace System {
         private String m_standardName;
         private String m_daylightName;
              
-        [System.Security.SecuritySafeCritical]  // auto-generated
-        internal CurrentSystemTimeZone() {
-            m_ticksOffset = nativeGetTimeZoneMinuteOffset() * TicksPerMinute;
-            m_standardName = null;
-            m_daylightName = null;
+        internal CurrentSystemTimeZone()
+        {
+            TimeZoneInfo local = TimeZoneInfo.Local;
+
+            m_ticksOffset = local.BaseUtcOffset.Ticks;
+            m_standardName = local.StandardName;
+            m_daylightName = local.DaylightName;
         }
     
-        public override String StandardName {
-            [System.Security.SecuritySafeCritical]  // auto-generated
-            get {
-                if (m_standardName == null) {
-                    m_standardName = nativeGetStandardName();
-                }
-                return (m_standardName);
+        public override String StandardName
+        {
+            get 
+            {
+                return m_standardName;
             }    
         }
 
-        public override String DaylightName {
-            [System.Security.SecuritySafeCritical]  // auto-generated
-            get {
-                if (m_daylightName == null) {
-                    m_daylightName = nativeGetDaylightName(); 
-                    if (m_daylightName == null) {
-                        m_daylightName = this.StandardName;
-                    }
-                }
-                return (m_daylightName);
+        public override String DaylightName
+        {
+            get
+            {
+                return m_daylightName;
             }
         }
 
-        internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst) {
+        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) {
+            if (daylightTime == null || daylightTime.Delta.Ticks == 0)
+            {
                 return offset.Ticks;
             }
             
@@ -107,57 +89,73 @@ namespace System {
             DateTime endTime = daylightTime.End - offset - daylightTime.Delta;
             DateTime ambiguousStart;
             DateTime ambiguousEnd;
-            if (daylightTime.Delta.Ticks > 0) {
+            
+            if (daylightTime.Delta.Ticks > 0)
+            {
                 ambiguousStart = endTime - daylightTime.Delta;
                 ambiguousEnd = endTime;
-            } else {
+            }
+            else
+            {
                 ambiguousStart = startTime;
                 ambiguousEnd = startTime - daylightTime.Delta;
             }
 
             Boolean isDst = false;
-            if (startTime > endTime) {
+            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 {
+            else
+            {
                 // In northern hemisphere, the daylight saving time starts in the middle of the year.
-                isDst = (time>=startTime && time<endTime);
+                isDst = (time >= startTime && time < endTime);
             }
-            if (isDst) {
+            
+            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 ) {
+                if (time >= ambiguousStart && time < ambiguousEnd )
+                {
                     isAmbiguousLocalDst = true;
                 }
             }
             return offset.Ticks;
         }
         
-        public override DateTime ToLocalTime(DateTime time) {
-            if (time.Kind == DateTimeKind.Local) {
+        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) {
+            if (tick > DateTime.MaxTicks)
+            {
                 return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
             }
-            if (tick<DateTime.MinTicks) {
+            if (tick < DateTime.MinTicks)
+            {
                 return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
             }
-            return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);            
+            return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
         }
 
         // Private object for locking instead of locking on a public type for SQL reliability work.
         private static Object s_InternalSyncObject;
-        private static Object InternalSyncObject {
-            get {
-                if (s_InternalSyncObject == null) {
+        private static Object InternalSyncObject
+        {
+            get
+            {
+                if (s_InternalSyncObject == null)
+                {
                     Object o = new Object();
                     Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
                 }
@@ -165,61 +163,50 @@ namespace System {
             }
         }
 
-
-        [System.Security.SecuritySafeCritical]  // auto-generated
-        public override DaylightTime GetDaylightChanges(int year) {
-            if (year < 1 || year > 9999) {
+        public override DaylightTime GetDaylightChanges(int year)
+        {
+            if (year < 1 || year > 9999)
+            {
                 throw new ArgumentOutOfRangeException(nameof(year), Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999));
             }
             Contract.EndContractBlock();
 
-            Object objYear = (Object)year;
-
-            if (!m_CachedDaylightChanges.Contains(objYear)) {
-                lock (InternalSyncObject) {
+            Object objYear = (Object) year;
 
-                    if (!m_CachedDaylightChanges.Contains(objYear)) {
+            if (!m_CachedDaylightChanges.Contains(objYear))
+            {
+                DaylightTime currentDaylightChanges = null;
 
-                        //
-                        // rawData is an array of 17 short (16 bit) numbers.
-                        // The first 8 numbers contains the 
-                        // year/month/day/dayOfWeek/hour/minute/second/millisecond for the starting time of daylight saving time.
-                        // The next 8 numbers contains the
-                        // year/month/day/dayOfWeek/hour/minute/second/millisecond for the ending time of daylight saving time.
-                        // The last short number is the delta to the standard offset in minutes.
-                        //
-                        short[] rawData = nativeGetDaylightChanges(year);
+                if (TimeZoneInfo.Local.SupportsDaylightSavingTime)
+                {
+                    DateTime start;
+                    DateTime end;
+                    TimeSpan delta;
 
-                        if (rawData == null) {
-                            //
-                            // If rawData is null, it means that daylight saving time is not used
-                            // in this timezone. So keep currentDaylightChanges as the empty array.
-                            //
-                            m_CachedDaylightChanges.Add(objYear, new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero));
-                        } else {
-                            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;
 
-                            //
-                            // Store the start of daylight saving time.
-                            //
-
-                            start = GetDayOfWeek(year, (rawData[0] != 0), rawData[1], rawData[2],
-                                                  rawData[3],
-                                                  rawData[4], rawData[5], rawData[6], rawData[7]);
+                            currentDaylightChanges = new DaylightTime(start, end, delta);
+                            break;
+                        }
+                    }
+                }
 
-                            //
-                            // Store the end of daylight saving time.
-                            //
-                            end = GetDayOfWeek(year, (rawData[8] != 0), rawData[9], rawData[10],
-                                                rawData[11],
-                                                rawData[12], rawData[13], rawData[14], rawData[15]);
+                if (currentDaylightChanges == null)
+                {
+                    currentDaylightChanges = new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero); 
+                }
 
-                            delta = new TimeSpan(rawData[16] * TicksPerMinute);
-                            DaylightTime currentDaylightChanges = new DaylightTime(start, end, delta);
-                            m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
-                        }
+                lock (InternalSyncObject)
+                {
+                    if (!m_CachedDaylightChanges.Contains(objYear))
+                    {
+                        m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
                     }
                 }
             }        
@@ -229,82 +216,17 @@ namespace System {
             return result;
         }
 
-        public override TimeSpan GetUtcOffset(DateTime time) {
-            if (time.Kind == DateTimeKind.Utc) {
+        public override TimeSpan GetUtcOffset(DateTime time)
+        {
+            if (time.Kind == DateTimeKind.Utc)
+            {
                 return TimeSpan.Zero;
             }
-            else {
+            else
+            {
                 return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);                    
             }
         }
 
-        //
-        // Return the (numberOfSunday)th day of week in a particular year/month.
-        //
-        private static DateTime GetDayOfWeek(int year, bool fixedDate, int month, int targetDayOfWeek, int numberOfSunday, int hour, int minute, int second, int millisecond) {
-            DateTime time;
-            
-            if (fixedDate) {
-                //
-                // Create a Fixed-Date transition time based on the supplied parameters
-                // For Fixed-Dated transition times, the 'numberOfSunday' parameter actually
-                // represents the day of the month.
-                //
-
-                // if the day is out of range for the month then use the last day of the month
-                int day = DateTime.DaysInMonth(year, month);
-
-                time = new DateTime(year, month, (day < numberOfSunday) ? day : numberOfSunday,
-                                  hour, minute, second, millisecond, DateTimeKind.Local);
-            }
-            else if (numberOfSunday <= 4) {
-                //
-                // Get the (numberOfSunday)th Sunday.
-                //
-                
-                time = new DateTime(year, month, 1, hour, minute, second, millisecond, DateTimeKind.Local);
-    
-                int dayOfWeek = (int)time.DayOfWeek;
-                int delta = targetDayOfWeek - dayOfWeek;
-                if (delta < 0) {
-                    delta += 7;
-                }
-                delta += 7 * (numberOfSunday - 1);
-    
-                if (delta > 0) {
-                    time = time.AddDays(delta);
-                }
-            } else {
-                //
-                // If numberOfSunday is greater than 4, we will get the last sunday.
-                //
-                Calendar cal = GregorianCalendar.GetDefaultInstance();            
-                time = new DateTime(year, month, cal.GetDaysInMonth(year, month), hour, minute, second, millisecond, DateTimeKind.Local);
-                // This is the day of week for the last day of the month.
-                int dayOfWeek = (int)time.DayOfWeek;
-                int delta = dayOfWeek - targetDayOfWeek;
-                if (delta < 0) {
-                    delta += 7;
-                }
-                
-                if (delta > 0) {
-                    time = time.AddDays(-delta);
-                }
-            }
-            return (time);
-        }
-
-        [System.Security.SecurityCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        internal extern static int nativeGetTimeZoneMinuteOffset();
-        [System.Security.SecurityCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        internal extern static String nativeGetDaylightName();
-        [System.Security.SecurityCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        internal extern static String nativeGetStandardName();
-        [System.Security.SecurityCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.InternalCall)]
-        internal extern static short[] nativeGetDaylightChanges(int year);
     } // class CurrentSystemTimeZone
 }
index 2a7544d..6d2852f 100644 (file)
@@ -319,24 +319,58 @@ namespace System {
             }
         }
 
+#if PLATFORM_UNIX
+        // The rules we use in Unix cares mostly about the start and end dates but doesn’t fill the transition start and end info. 
+        // as the rules now is public, we should fill it properly so the caller doesn’t have to know how we use it internally 
+        // and can use it as it is used in Windows
 
-        // ---- SECTION: public methods --------------*
+        private AdjustmentRule[] GetFilledRules()
+        {
+            Contract.Assert(m_adjustmentRules != null, "m_adjustmentRules expected to be not null");
+            AdjustmentRule[] rules = new AdjustmentRule[m_adjustmentRules.Length];
+
+            for (int i = 0; i < m_adjustmentRules.Length; i++)
+            {
+                var rule = m_adjustmentRules[i];
+                var start = rule.DateStart.Kind == DateTimeKind.Utc ?
+                            new DateTime(TimeZoneInfo.ConvertTime(rule.DateStart, this).Ticks, DateTimeKind.Unspecified) :
+                            rule.DateStart;
+                var end = rule.DateEnd.Kind == DateTimeKind.Utc ?
+                            new DateTime(TimeZoneInfo.ConvertTime(rule.DateEnd, this).Ticks - 1, DateTimeKind.Unspecified) :
+                            rule.DateEnd;
+
+                var startTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, start.Hour, start.Minute, start.Second), start.Month, start.Day);
+                var endTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, end.Hour, end.Minute, end.Second), end.Month, end.Day);
+
+                rules[i] = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(start.Date, end.Date, rule.DaylightDelta, startTransition, endTransition);
+            }
+
+            return rules;
+        }
+#endif // PLATFORM_UNIX        
 
+        // ---- SECTION: public methods --------------*
         //
         // GetAdjustmentRules -
         //
         // returns a cloned array of AdjustmentRule objects
         //
-        public AdjustmentRule [] GetAdjustmentRules() {
-            if (m_adjustmentRules == null) {
-                return new AdjustmentRule[0];
+        public AdjustmentRule [] GetAdjustmentRules()
+        {
+            if (m_adjustmentRules == null)
+            {
+                return Array.Empty<AdjustmentRule>();
             }
-            else {
-                return (AdjustmentRule[])m_adjustmentRules.Clone();
+            else
+            {
+#if PLATFORM_UNIX
+                return GetFilledRules(); 
+#else
+                return (AdjustmentRule[]) m_adjustmentRules.Clone();
+#endif // PLATFORM_UNIX        
             }
         }
 
-
         //
         // GetAmbiguousTimeOffsets -
         //
@@ -2719,7 +2753,7 @@ namespace System {
 
                 // As we get the associated rule using the adjusted targetTime, we should use the adjusted year (targetTime.Year) too as after adding the baseOffset, 
                 // sometimes the year value can change if the input datetime was very close to the beginning or the end of the year. Examples of such cases:
-                //      \93Libya Standard Time\94 when used with the date 2011-12-31T23:59:59.9999999Z
+                //      Libya Standard Time when used with the date 2011-12-31T23:59:59.9999999Z
                 //      "W. Australia Standard Time" used with date 2005-12-31T23:59:00.0000000Z
                 DateTime targetTime = time + baseOffset;
                 year = targetTime.Year;
@@ -2856,7 +2890,7 @@ namespace System {
         //
         // Helper function that converts a year and TransitionTime into a DateTime
         //
-        static private DateTime TransitionTimeToDateTime(Int32 year, TransitionTime transitionTime) {
+        internal static DateTime TransitionTimeToDateTime(Int32 year, TransitionTime transitionTime) {
             DateTime value;
             DateTime timeOfDay = transitionTime.TimeOfDay;
 
index 7242314..1ac8f39 100644 (file)
@@ -195,15 +195,6 @@ FCFuncStart(gTimeSpanFuncs)
 FCFuncEnd()
 #endif // !FEATURE_CORECLR
 
-#ifndef FEATURE_CORECLR  // FCalls used by System.TimeZone
-FCFuncStart(gTimeZoneFuncs)
-    FCFuncElement("nativeGetTimeZoneMinuteOffset", COMNlsInfo::nativeGetTimeZoneMinuteOffset)
-    FCFuncElement("nativeGetStandardName", COMNlsInfo::nativeGetStandardName)
-    FCFuncElement("nativeGetDaylightName", COMNlsInfo::nativeGetDaylightName)
-    FCFuncElement("nativeGetDaylightChanges", COMNlsInfo::nativeGetDaylightChanges)
-FCFuncEnd()
-#endif // FEATURE_CORECLR
-
 FCFuncStart(gObjectFuncs)
     FCIntrinsic("GetType", ObjectNative::GetClass, CORINFO_INTRINSIC_Object_GetType)
     FCFuncElement("MemberwiseClone", ObjectNative::Clone)
@@ -2212,9 +2203,6 @@ FCClassElement("CultureData", "System.Globalization", gCultureDataFuncs)
 FCClassElement("CultureInfo", "System.Globalization", gCultureInfoFuncs)
 #endif
 FCClassElement("Currency", "System", gCurrencyFuncs)
-#ifndef FEATURE_CORECLR
-FCClassElement("CurrentSystemTimeZone", "System", gTimeZoneFuncs)
-#endif // FEATURE_CORECLR
 FCClassElement("CustomAttribute", "System.Reflection", gCOMCustomAttributeFuncs)
 FCClassElement("CustomAttributeEncodedArgument", "System.Reflection", gCustomAttributeEncodedArgument)
 FCClassElement("DateMarshaler", "System.StubHelpers", gDateMarshalerFuncs)