public DateTime GetLocalTime(string timeZoneKey, DateTime utc) { // Convert to Win32 SYSTEMTIME SYSTEMTIME utcSysTime = new SYSTEMTIME { wYear = (ushort)utc.Year, wMonth = (ushort)utc.Month, wDay = (ushort)utc.Day, wHour = (ushort)utc.Hour, wMinute = (ushort)utc.Minute, wSecond = (ushort)utc.Second, wMilliseconds = (ushort)utc.Millisecond }; // Convert to local time DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicTzis[timeZoneKey]; TIME_ZONE_INFORMATION tzi = new TIME_ZONE_INFORMATION(); GetTimeZoneInformationForYear((ushort)utc.Year, ref dtzi, out tzi); SYSTEMTIME localSysTime = new SYSTEMTIME(); SystemTimeToTzSpecificLocalTime(ref tzi, ref utcSysTime, out localSysTime); // Convert SYSTEMTIME to DateTime return(new DateTime(localSysTime.wYear, localSysTime.wMonth, localSysTime.wDay, localSysTime.wHour, localSysTime.wMinute, localSysTime.wSecond, localSysTime.wMilliseconds)); }
private TimeZoneInfoEx(DYNAMIC_TIME_ZONE_INFORMATION source) { _source = source; Name = source.TimeZoneKeyName; StandardName = source.StandardName; DaylightName = source.DaylightName; BaseUtcOffset = new TimeSpan(0, -(source.Bias + source.StandardBias), 0); }
internal static AdjustmentRule CreateAdjustmentRuleFromTimeZoneInformation(ref DYNAMIC_TIME_ZONE_INFORMATION timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) { bool supportsDst = (timeZoneInformation.TZI.StandardDate.wMonth != 0); if (!supportsDst) { if (timeZoneInformation.TZI.Bias == defaultBaseUtcOffset) { // this rule will not contain any information to be used to adjust dates. just ignore it return(null); } return(AdjustmentRule.CreateAdjustmentRule( startDate, endDate, TimeSpan.Zero, // no daylight saving transition TransitionTime.CreateFixedDateRule(DateTime.MinValue, 1, 1), TransitionTime.CreateFixedDateRule(DateTime.MinValue.AddMilliseconds(1), 1, 1), new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.TZI.Bias, 0))); // Bias delta is all what we need from this rule } // // Create an AdjustmentRule with TransitionTime objects // TransitionTime daylightTransitionStart; if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionStart, true /* start date */)) { return(null); } TransitionTime daylightTransitionEnd; if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionEnd, false /* end date */)) { return(null); } if (daylightTransitionStart.Equals(daylightTransitionEnd)) { // this happens when the time zone does support DST but the OS has DST disabled return(null); } return(AdjustmentRule.CreateAdjustmentRule( startDate, endDate, new TimeSpan(0, -timeZoneInformation.TZI.DaylightBias, 0), (TransitionTime)daylightTransitionStart, (TransitionTime)daylightTransitionEnd, new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.TZI.Bias, 0))); }
public static extern Win32Error EnumDynamicTimeZoneInformation(uint dwIndex, out DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation);
public static extern int GetDynamicTimeZoneInformation(out DYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation);
public static extern bool TzSpecificLocalTimeToSystemTimeEx([In] ref DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation, [In] ref SYSTEMTIME lpLocalTime, out SYSTEMTIME lpUniversalTime);
internal static extern bool GetTimeZoneInformationForYear([In] short wYear, [In] ref DYNAMIC_TIME_ZONE_INFORMATION pdtzi, out TIME_ZONE_INFORMATION ptzi);
internal static TimeZoneInfo TryCreateTimeZone(DYNAMIC_TIME_ZONE_INFORMATION timeZoneInformation) { uint firstYear = 0, lastYear = 0; AdjustmentRule rule; AdjustmentRule[] zoneRules = null; int defaultBaseUtcOffset = timeZoneInformation.TZI.Bias; if (String.IsNullOrEmpty(timeZoneInformation.TimeZoneKeyName)) { return(null); } // // First get the adjustment rules // try { if (GetDynamicTimeZoneInformationEffectiveYears(ref timeZoneInformation, out firstYear, out lastYear) != 0) { firstYear = lastYear = 0; } } catch { // If we don't have GetDynamicTimeZoneInformationEffectiveYears() firstYear = lastYear = 0; } if (firstYear == lastYear) { rule = CreateAdjustmentRuleFromTimeZoneInformation(ref timeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); if (rule != null) { zoneRules = new AdjustmentRule [1] { rule } } ; } else { DYNAMIC_TIME_ZONE_INFORMATION dtzi = default(DYNAMIC_TIME_ZONE_INFORMATION); List <AdjustmentRule> rules = new List <AdjustmentRule> (); // // First rule // if (!GetTimeZoneInformationForYear((ushort)firstYear, ref timeZoneInformation, out dtzi.TZI)) { return(null); } rule = CreateAdjustmentRuleFromTimeZoneInformation(ref dtzi, DateTime.MinValue.Date, new DateTime((int)firstYear, 12, 31), defaultBaseUtcOffset); if (rule != null) { rules.Add(rule); } for (uint i = firstYear + 1; i < lastYear; i++) { if (!GetTimeZoneInformationForYear((ushort)i, ref timeZoneInformation, out dtzi.TZI)) { return(null); } rule = CreateAdjustmentRuleFromTimeZoneInformation(ref dtzi, new DateTime((int)i, 1, 1), new DateTime((int)i, 12, 31), defaultBaseUtcOffset); if (rule != null) { rules.Add(rule); } } // // Last rule // if (!GetTimeZoneInformationForYear((ushort)lastYear, ref timeZoneInformation, out dtzi.TZI)) { return(null); } rule = CreateAdjustmentRuleFromTimeZoneInformation(ref dtzi, new DateTime((int)lastYear, 1, 1), DateTime.MaxValue.Date, defaultBaseUtcOffset); if (rule != null) { rules.Add(rule); } if (rules.Count > 0) { zoneRules = rules.ToArray(); } } return(new TimeZoneInfo( timeZoneInformation.TimeZoneKeyName, new TimeSpan(0, -(timeZoneInformation.TZI.Bias), 0), timeZoneInformation.TZI.StandardName, // we use the display name as the standared names timeZoneInformation.TZI.StandardName, timeZoneInformation.TZI.DaylightName, zoneRules, false)); }
static extern byte GetTimeZoneInformationForYear(ushort year, ref DYNAMIC_TIME_ZONE_INFORMATION dtzi, out TIME_ZONE_INFORMATION tzi);
internal static extern int EnumDynamicTimeZoneInformation([In] int dwIndex, out DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation);
internal extern static bool GetTimeZoneInformationForYear(ushort wYear, ref DYNAMIC_TIME_ZONE_INFORMATION pdtzi, out TIME_ZONE_INFORMATION ptzi);
internal extern static uint GetDynamicTimeZoneInformationEffectiveYears(ref DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation, out uint FirstYear, out uint LastYear);
internal extern static uint GetDynamicTimeZoneInformation(out DYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation);
public static extern bool SetDynamicTimeZoneInformation([In] ref DYNAMIC_TIME_ZONE_INFORMATION lpTimeZoneInformation);
public static extern bool GetTimeZoneInformationForYear([In] ushort wYear, [In] ref DYNAMIC_TIME_ZONE_INFORMATION pdtzi, ref TIME_ZONE_INFORMATION ptzi);
internal static extern int GetDynamicTimeZoneInformation(out DYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation);
static extern uint EnumDynamicTimeZoneInformation(uint index, ref DYNAMIC_TIME_ZONE_INFORMATION dynamicTzi);
public TimeZoneManager() { uint index = 0; DYNAMIC_TIME_ZONE_INFORMATION tzi = new DYNAMIC_TIME_ZONE_INFORMATION(); List <TimeZoneDisplayInfo> displayInformation = new List <TimeZoneDisplayInfo>(); // Enumerate through time zones while (0 == EnumDynamicTimeZoneInformation(index, ref tzi)) { dynamicTzis.Add(tzi.TimeZoneKeyName, tzi); // Create TimeZoneDisplayInfo for public property TimeZoneDisplayInfo displayInfo = new TimeZoneDisplayInfo { Bias = tzi.Bias, TimeZoneKey = tzi.TimeZoneKeyName }; // Look up the display string if (displayStrings.ContainsKey(tzi.TimeZoneKeyName)) { displayInfo.Display = displayStrings[tzi.TimeZoneKeyName]; } else if (displayStrings.ContainsKey(tzi.StandardName)) { displayInfo.Display = displayStrings[tzi.StandardName]; } // Or calculate one else { if (tzi.Bias == 0) { displayInfo.Display = "(UTC) "; } else { displayInfo.Display = String.Format("(UTC{0}{1:D2}:{2:D2}) ", tzi.Bias > 0 ? '-' : '+', Math.Abs(tzi.Bias) / 60, Math.Abs(tzi.Bias) % 60); } displayInfo.Display += tzi.TimeZoneKeyName; } // Add to collection displayInformation.Add(displayInfo); // Prepare for next iteration index += 1; tzi = new DYNAMIC_TIME_ZONE_INFORMATION(); } // Sort the display information items displayInformation.Sort((TimeZoneDisplayInfo info1, TimeZoneDisplayInfo info2) => { return(info2.Bias.CompareTo(info1.Bias)); }); // Set to the publicly available property this.DisplayInformation = displayInformation; }
// // TransitionTimeFromTimeZoneInformation - // // Converts a TimeZoneInformation (REG_TZI_FORMAT struct) to a TransitionTime // // * when the argument 'readStart' is true the corresponding daylightTransitionTimeStart field is read // * when the argument 'readStart' is false the corresponding dayightTransitionTimeEnd field is read // private static bool TransitionTimeFromTimeZoneInformation(DYNAMIC_TIME_ZONE_INFORMATION timeZoneInformation, out TransitionTime transitionTime, bool readStartDate) { // // SYSTEMTIME - // // If the time zone does not support daylight saving time or if the caller needs // to disable daylight saving time, the wMonth member in the SYSTEMTIME structure // must be zero. If this date is specified, the DaylightDate value in the // TIME_ZONE_INFORMATION structure must also be specified. Otherwise, the system // assumes the time zone data is invalid and no changes will be applied. // bool supportsDst = (timeZoneInformation.TZI.StandardDate.wMonth != 0); if (!supportsDst) { transitionTime = default(TransitionTime); return(false); } // // SYSTEMTIME - // // * FixedDateRule - // If the Year member is not zero, the transition date is absolute; it will only occur one time // // * FloatingDateRule - // To select the correct day in the month, set the Year member to zero, the Hour and Minute // members to the transition time, the DayOfWeek member to the appropriate weekday, and the // Day member to indicate the occurence of the day of the week within the month (first through fifth). // // Using this notation, specify the 2:00a.m. on the first Sunday in April as follows: // Hour = 2, // Month = 4, // DayOfWeek = 0, // Day = 1. // // Specify 2:00a.m. on the last Thursday in October as follows: // Hour = 2, // Month = 10, // DayOfWeek = 4, // Day = 5. // if (readStartDate) { // // read the "daylightTransitionStart" // if (timeZoneInformation.TZI.DaylightDate.wYear == 0) { transitionTime = TransitionTime.CreateFloatingDateRule( new DateTime(1, /* year */ 1, /* month */ 1, /* day */ timeZoneInformation.TZI.DaylightDate.wHour, timeZoneInformation.TZI.DaylightDate.wMinute, timeZoneInformation.TZI.DaylightDate.wSecond, timeZoneInformation.TZI.DaylightDate.wMilliseconds), timeZoneInformation.TZI.DaylightDate.wMonth, timeZoneInformation.TZI.DaylightDate.wDay, /* Week 1-5 */ (DayOfWeek)timeZoneInformation.TZI.DaylightDate.wDayOfWeek); } else { transitionTime = TransitionTime.CreateFixedDateRule( new DateTime(1, /* year */ 1, /* month */ 1, /* day */ timeZoneInformation.TZI.DaylightDate.wHour, timeZoneInformation.TZI.DaylightDate.wMinute, timeZoneInformation.TZI.DaylightDate.wSecond, timeZoneInformation.TZI.DaylightDate.wMilliseconds), timeZoneInformation.TZI.DaylightDate.wMonth, timeZoneInformation.TZI.DaylightDate.wDay); } } else { // // read the "daylightTransitionEnd" // if (timeZoneInformation.TZI.StandardDate.wYear == 0) { transitionTime = TransitionTime.CreateFloatingDateRule( new DateTime(1, /* year */ 1, /* month */ 1, /* day */ timeZoneInformation.TZI.StandardDate.wHour, timeZoneInformation.TZI.StandardDate.wMinute, timeZoneInformation.TZI.StandardDate.wSecond, timeZoneInformation.TZI.StandardDate.wMilliseconds), timeZoneInformation.TZI.StandardDate.wMonth, timeZoneInformation.TZI.StandardDate.wDay, /* Week 1-5 */ (DayOfWeek)timeZoneInformation.TZI.StandardDate.wDayOfWeek); } else { transitionTime = TransitionTime.CreateFixedDateRule( new DateTime(1, /* year */ 1, /* month */ 1, /* day */ timeZoneInformation.TZI.StandardDate.wHour, timeZoneInformation.TZI.StandardDate.wMinute, timeZoneInformation.TZI.StandardDate.wSecond, timeZoneInformation.TZI.StandardDate.wMilliseconds), timeZoneInformation.TZI.StandardDate.wMonth, timeZoneInformation.TZI.StandardDate.wDay); } } return(true); }