Пример #1
0
        private TimeZoneInfo(Win32Native.TimeZoneInformation zone, bool dstDisabled)
        {
            if (string.IsNullOrEmpty(zone.StandardName))
            {
                _id = LocalId;  // the ID must contain at least 1 character - initialize _id to "Local"
            }
            else
            {
                _id = zone.StandardName;
            }
            _baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0);

            if (!dstDisabled)
            {
                // only create the adjustment rule if DST is enabled
                Win32Native.RegistryTimeZoneInformation regZone = new Win32Native.RegistryTimeZoneInformation(zone);
                AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(regZone, DateTime.MinValue.Date, DateTime.MaxValue.Date, zone.Bias);
                if (rule != null)
                {
                    _adjustmentRules    = new AdjustmentRule[1];
                    _adjustmentRules[0] = rule;
                }
            }

            ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out _supportsDaylightSavingTime);
            _displayName         = zone.StandardName;
            _standardDisplayName = zone.StandardName;
            _daylightDisplayName = zone.DaylightName;
        }
Пример #2
0
        /// <summary>
        /// Helper function that compares a TimeZoneInformation struct to a time zone registry entry.
        /// </summary>
        private static bool TryCompareTimeZoneInformationToRegistry(Win32Native.TimeZoneInformation timeZone, string id, out bool dstDisabled)
        {
            dstDisabled = false;

            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id, writable: false))
            {
                if (key == null)
                {
                    return(false);
                }

                Win32Native.RegistryTimeZoneInformation registryTimeZoneInfo;
                byte[] regValue = key.GetValue(TimeZoneInfoValue, null, RegistryValueOptions.None) as byte[];
                if (regValue == null || regValue.Length != RegByteLength)
                {
                    return(false);
                }
                registryTimeZoneInfo = new Win32Native.RegistryTimeZoneInformation(regValue);

                //
                // first compare the bias and standard date information between the data from the Win32 API
                // and the data from the registry...
                //
                bool result = TryCompareStandardDate(timeZone, registryTimeZoneInfo);

                if (!result)
                {
                    return(false);
                }

                result = dstDisabled || CheckDaylightSavingTimeNotSupported(timeZone) ||
                         //
                         // since Daylight Saving Time is not "disabled", do a straight comparision between
                         // the Win32 API data and the registry data ...
                         //
                         (timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias &&
                          timeZone.DaylightDate.Year == registryTimeZoneInfo.DaylightDate.Year &&
                          timeZone.DaylightDate.Month == registryTimeZoneInfo.DaylightDate.Month &&
                          timeZone.DaylightDate.DayOfWeek == registryTimeZoneInfo.DaylightDate.DayOfWeek &&
                          timeZone.DaylightDate.Day == registryTimeZoneInfo.DaylightDate.Day &&
                          timeZone.DaylightDate.Hour == registryTimeZoneInfo.DaylightDate.Hour &&
                          timeZone.DaylightDate.Minute == registryTimeZoneInfo.DaylightDate.Minute &&
                          timeZone.DaylightDate.Second == registryTimeZoneInfo.DaylightDate.Second &&
                          timeZone.DaylightDate.Milliseconds == registryTimeZoneInfo.DaylightDate.Milliseconds);

                // Finally compare the "StandardName" string value...
                //
                // we do not compare "DaylightName" as this TimeZoneInformation field may contain
                // either "StandardName" or "DaylightName" depending on the time of year and current machine settings
                //
                if (result)
                {
                    string registryStandardName = key.GetValue(StandardValue, string.Empty, RegistryValueOptions.None) as string;
                    result = string.Equals(registryStandardName, timeZone.StandardName, StringComparison.Ordinal);
                }
                return(result);
            }
        }
Пример #3
0
 /// <summary>
 /// Helper function to check if the current TimeZoneInformation struct does not support DST.
 /// This check returns true when the DaylightDate == StandardDate.
 /// This check is only meant to be used for "Local".
 /// </summary>
 private static bool CheckDaylightSavingTimeNotSupported(Win32Native.TimeZoneInformation timeZone) =>
 timeZone.DaylightDate.Year == timeZone.StandardDate.Year &&
 timeZone.DaylightDate.Month == timeZone.StandardDate.Month &&
 timeZone.DaylightDate.DayOfWeek == timeZone.StandardDate.DayOfWeek &&
 timeZone.DaylightDate.Day == timeZone.StandardDate.Day &&
 timeZone.DaylightDate.Hour == timeZone.StandardDate.Hour &&
 timeZone.DaylightDate.Minute == timeZone.StandardDate.Minute &&
 timeZone.DaylightDate.Second == timeZone.StandardDate.Second &&
 timeZone.DaylightDate.Milliseconds == timeZone.StandardDate.Milliseconds;
Пример #4
0
        /// <summary>
        /// Helper function for retrieving the local system time zone.
        /// May throw COMException, TimeZoneNotFoundException, InvalidTimeZoneException.
        /// Assumes cachedData lock is taken.
        /// </summary>
        /// <returns>A new TimeZoneInfo instance.</returns>
        private static TimeZoneInfo GetLocalTimeZone(CachedData cachedData)
        {
            Debug.Assert(Monitor.IsEntered(cachedData));

            string id = null;

            //
            // Try using the "kernel32!GetDynamicTimeZoneInformation" API to get the "id"
            //
            var dynamicTimeZoneInformation = new Win32Native.DynamicTimeZoneInformation();

            // call kernel32!GetDynamicTimeZoneInformation...
            long result = UnsafeNativeMethods.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation);

            if (result == Win32Native.TIME_ZONE_ID_INVALID)
            {
                // return a dummy entry
                return(CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId));
            }

            var timeZoneInformation = new Win32Native.TimeZoneInformation(dynamicTimeZoneInformation);

            bool dstDisabled = dynamicTimeZoneInformation.DynamicDaylightTimeDisabled;

            // check to see if we can use the key name returned from the API call
            if (!string.IsNullOrEmpty(dynamicTimeZoneInformation.TimeZoneKeyName))
            {
                TimeZoneInfo zone;
                Exception    ex;

                if (TryGetTimeZone(dynamicTimeZoneInformation.TimeZoneKeyName, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success)
                {
                    // successfully loaded the time zone from the registry
                    return(zone);
                }
            }

            // the key name was not returned or it pointed to a bogus entry - search for the entry ourselves
            id = FindIdFromTimeZoneInformation(timeZoneInformation, out dstDisabled);

            if (id != null)
            {
                TimeZoneInfo zone;
                Exception    ex;
                if (TryGetTimeZone(id, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success)
                {
                    // successfully loaded the time zone from the registry
                    return(zone);
                }
            }

            // We could not find the data in the registry.  Fall back to using
            // the data from the Win32 API
            return(GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled));
        }
Пример #5
0
 /// <summary>
 /// Helper function that compares the StandardBias and StandardDate portion a
 /// TimeZoneInformation struct to a time zone registry entry.
 /// </summary>
 private static bool TryCompareStandardDate(Win32Native.TimeZoneInformation timeZone, Win32Native.RegistryTimeZoneInformation registryTimeZoneInfo) =>
 timeZone.Bias == registryTimeZoneInfo.Bias &&
 timeZone.StandardBias == registryTimeZoneInfo.StandardBias &&
 timeZone.StandardDate.Year == registryTimeZoneInfo.StandardDate.Year &&
 timeZone.StandardDate.Month == registryTimeZoneInfo.StandardDate.Month &&
 timeZone.StandardDate.DayOfWeek == registryTimeZoneInfo.StandardDate.DayOfWeek &&
 timeZone.StandardDate.Day == registryTimeZoneInfo.StandardDate.Day &&
 timeZone.StandardDate.Hour == registryTimeZoneInfo.StandardDate.Hour &&
 timeZone.StandardDate.Minute == registryTimeZoneInfo.StandardDate.Minute &&
 timeZone.StandardDate.Second == registryTimeZoneInfo.StandardDate.Second &&
 timeZone.StandardDate.Milliseconds == registryTimeZoneInfo.StandardDate.Milliseconds;
Пример #6
0
        /// <summary>
        /// Helper function that searches the registry for a time zone entry
        /// that matches the TimeZoneInformation struct.
        /// </summary>
        private static string FindIdFromTimeZoneInformation(Win32Native.TimeZoneInformation timeZone, out bool dstDisabled)
        {
            dstDisabled = false;

            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive, writable: false))
            {
                if (key == null)
                {
                    return(null);
                }

                foreach (string keyName in key.GetSubKeyNames())
                {
                    if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled))
                    {
                        return(keyName);
                    }
                }
            }

            return(null);
        }
Пример #7
0
        /// <summary>
        /// Helper function used by 'GetLocalTimeZone()' - this function wraps a bunch of
        /// try/catch logic for handling the TimeZoneInfo private constructor that takes
        /// a Win32Native.TimeZoneInformation structure.
        /// </summary>
        private static TimeZoneInfo GetLocalTimeZoneFromWin32Data(Win32Native.TimeZoneInformation timeZoneInformation, bool dstDisabled)
        {
            // first try to create the TimeZoneInfo with the original 'dstDisabled' flag
            try
            {
                return(new TimeZoneInfo(timeZoneInformation, dstDisabled));
            }
            catch (ArgumentException) { }
            catch (InvalidTimeZoneException) { }

            // if 'dstDisabled' was false then try passing in 'true' as a last ditch effort
            if (!dstDisabled)
            {
                try
                {
                    return(new TimeZoneInfo(timeZoneInformation, dstDisabled: true));
                }
                catch (ArgumentException) { }
                catch (InvalidTimeZoneException) { }
            }

            // the data returned from Windows is completely bogus; return a dummy entry
            return(CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId));
        }