internal TimeZoneInfo ToTimeZoneInfo() { if (this.daylightTime.HasTransitionTime && this.standardTime.HasTransitionTime) { AdjustmentRule adjustmentRule = AdjustmentRule.CreateAdjustmentRule( DateTime.MinValue.Date, DateTime.MaxValue.Date, -this.daylightTime.Delta, this.daylightTime.ToTransitionTime(), this.standardTime.ToTransitionTime()); return(TimeZoneExtensions.CreateCustomTimeZone( Guid.NewGuid().ToString(), -this.bias, "Custom time zone", "Standard time", "Daylight time", new AdjustmentRule[] { adjustmentRule })); } else { // Create no DST time zone return(TimeZoneExtensions.CreateCustomTimeZone( Guid.NewGuid().ToString(), -this.bias, "Custom time zone", "Standard time")); } }
private static void TZif_CreateMiddleMultiYearRules(ref List <AdjustmentRule> rulesList, TimeSpan daylightBias, DateTime endTransitionDate) { // // [AdjustmentRule #1] // middle-year all-DST rule // [1947/06/16 - 1947/11/15] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * 5 months long, stopping at month 6 or 11 // [end : 12/15 ] // notice how the _start and end_ are outside the range // // [AdjustmentRule #2] // middle-year all-DST rule // [1947/11/16 - 1947/06/15] // * starts 1 day after last day in previous rule // [start: 10/01 ] // * 7 months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _start and end_ are outside the range // // ......................... AdjustmentRule prevRule = rulesList[rulesList.Count - 1]; // grab the first element of the MultiYearRule sequence DateTime endDate; // // Choosing the last endDate based on the endTransitionDate // // endTransitionDate.Month -> end // 1 4|5 8|9 12 // [11/15 <-]|[11/15 <-]|[06/15 <-] // if (endTransitionDate.Month <= 8) { // set the end date to 11/15/YYYY-1 endDate = new DateTime(endTransitionDate.Year - 1, 11, 15); } else { // set the end date to 06/15/YYYY endDate = new DateTime(endTransitionDate.Year, 06, 15); } while (prevRule.DateEnd < endDate) { // the last endDate will be on either 06/15 or 11/15 int y = prevRule.DateEnd.Year; if (prevRule.DateEnd.Month <= 6) { // create a rule from 06/16/YYYY to 11/15/YYYY AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(new DateTime(y, 06, 16), new DateTime(y, 11, 15), daylightBias, s_transition5_15, s_transition12_15); prevRule = r; rulesList.Add(r); } else { // create a rule from 11/16/YYYY to 06/15/YYYY+1 AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(new DateTime(y, 11, 16), new DateTime(y + 1, 06, 15), daylightBias, s_transition10_15, s_transition7_15); prevRule = r; rulesList.Add(r); } } }
private static void TZif_CreateFirstMultiYearRule(ref List <AdjustmentRule> rulesList, TimeSpan daylightBias, DateTime startTransitionDate, int DstStartIndex, int dstStartTypeIndex, int dstEndTypeIndex, DateTime[] dts, TZifType[] transitionType, Byte[] typeOfLocalTime, bool[] StandardTime, bool[] GmtTime) { // [AdjustmentRule #0] // start rule // [1946/09/31 - 1947/06/15] // * starts 1 day prior to startTransitionDate // [start: 10/01 @4:00 ] // * N months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _end_ is outside the range DateTime startDate; DateTime endDate; TransitionTime dstStart; TransitionTime dstEnd; TimeSpan startTransitionOffset = (DstStartIndex > 0 ? transitionType[typeOfLocalTime[DstStartIndex - 1]].UtcOffset : transitionType[dstEndTypeIndex].UtcOffset); dstStart = TZif_CalculateTransitionTime(startTransitionDate, startTransitionOffset, transitionType[dstStartTypeIndex], StandardTime[dstStartTypeIndex], GmtTime[dstStartTypeIndex], out startDate); // // Choosing the endDate based on the startDate: // // startTransitionDate.Month -> end // 1 4|5 8|9 12 // [-> 06/15]|[-> 11/15]|[-> 06/15] // int startDateMonth = startDate.Month; int startDateYear = startDate.Year; if (startDateMonth <= 4) { endDate = new DateTime(startDateYear, 06, 15); dstEnd = s_transition7_15; } else if (startDateMonth <= 8) { endDate = new DateTime(startDateYear, 11, 15); dstEnd = s_transition12_15; } else if (startDateYear < 9999) { endDate = new DateTime(startDateYear + 1, 06, 15); dstEnd = s_transition7_15; } else { endDate = DateTime.MaxValue; dstEnd = s_transition7_15; } AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(startDate, endDate, daylightBias, dstStart, dstEnd); rulesList.Add(r); }
/// <summary> /// Converts a Win32Native.RegistryTimeZoneInformation (REG_TZI_FORMAT struct) to an AdjustmentRule. /// </summary> private static AdjustmentRule CreateAdjustmentRuleFromTimeZoneInformation(Win32Native.RegistryTimeZoneInformation timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) { bool supportsDst = timeZoneInformation.StandardDate.Month != 0; if (!supportsDst) { if (timeZoneInformation.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.Bias, 0), // Bias delta is all what we need from this rule noDaylightTransitions: false)); } // // Create an AdjustmentRule with TransitionTime objects // TransitionTime daylightTransitionStart; if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionStart, readStartDate: true)) { return(null); } TransitionTime daylightTransitionEnd; if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionEnd, readStartDate: false)) { 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.DaylightBias, 0), daylightTransitionStart, daylightTransitionEnd, new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), noDaylightTransitions: false)); }
private static AdjustmentRule R(long dateStart, long dateEnd, long daylightDelta, TransitionTime daylightTransitionStart, TransitionTime daylightTransitionEnd, long baseUtcOffsetDelta) { var rule = AdjustmentRule.CreateAdjustmentRule( DateTime.FromBinary(dateStart), DateTime.FromBinary(dateEnd), TimeSpan.FromTicks(daylightDelta), daylightTransitionStart, daylightTransitionEnd); BaseUtcOffsetDeltaField.SetValue(rule, TimeSpan.FromTicks(baseUtcOffsetDelta)); return(rule); }
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))); }
/// <summary> /// Creates a time zone adjustment rule. /// </summary> /// <param name="startDate">The start date of the adjustment rule.</param> /// <param name="endDate">The end date of the adjustment rule.</param> /// <returns>An TimeZoneInfo.AdjustmentRule.</returns> internal AdjustmentRule CreateAdjustmentRule(DateTime startDate, DateTime endDate) { // If there is only one transition, we can't create an adjustment rule. We have to assume // that the base offset to UTC is unchanged. if (this.transitions.Count == 1) { return(null); } return(AdjustmentRule.CreateAdjustmentRule( startDate.Date, endDate.Date, this.GetDaylightDelta(), this.TransitionToDaylight.CreateTransitionTime(), this.TransitionToStandard.CreateTransitionTime())); }
private static void TZif_CreateLastMultiYearRule(ref List <AdjustmentRule> rulesList, TimeSpan daylightBias, DateTime endTransitionDate, int DstStartIndex, int dstStartTypeIndex, int DstEndIndex, int dstEndTypeIndex, DateTime[] dts, TZifType[] transitionType, Byte[] typeOfLocalTime, bool[] StandardTime, bool[] GmtTime) { // [AdjustmentRule #N] // end rule // [1963/06/16 - 1946/10/02] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * N months long, stopping 1 day after endTransitionDate // [end : 10/01 ] // notice how the _start_ is outside the range DateTime endDate; TransitionTime dstEnd; TimeSpan endTransitionOffset = (DstEndIndex > 0 ? transitionType[typeOfLocalTime[DstEndIndex - 1]].UtcOffset : transitionType[dstStartTypeIndex].UtcOffset); dstEnd = TZif_CalculateTransitionTime(endTransitionDate, endTransitionOffset, transitionType[dstEndTypeIndex], StandardTime[dstEndTypeIndex], GmtTime[dstEndTypeIndex], out endDate); if (DstStartIndex >= DstEndIndex) { // we found a DST start but no DST end endDate = DateTime.MaxValue.Date; } AdjustmentRule prevRule = rulesList[rulesList.Count - 1]; // grab the last element of the MultiYearRule sequence int y = prevRule.DateEnd.Year; if (prevRule.DateEnd.Month <= 6) { // create a rule from 06/16/YYYY to endDate AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(new DateTime(y, 06, 16), endDate, daylightBias, s_transition5_15, dstEnd); rulesList.Add(r); } else { // create a rule from 11/16/YYYY to endDate AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(new DateTime(y, 11, 16), endDate, daylightBias, s_transition10_15, dstEnd); rulesList.Add(r); } }
private static bool TZif_GenerateAdjustmentRule(ref int startIndex, ref List <AdjustmentRule> rulesList, DateTime[] dts, Byte[] typeOfLocalTime, TZifType[] transitionType, Boolean[] StandardTime, Boolean[] GmtTime) { int index = startIndex; bool Dst = false; int DstStartIndex = -1; int DstEndIndex = -1; DateTime startDate = DateTime.MinValue.Date; DateTime endDate = DateTime.MaxValue.Date; // find the next DST transition start time index while (!Dst && index < typeOfLocalTime.Length) { int typeIndex = typeOfLocalTime[index]; if (typeIndex < transitionType.Length && transitionType[typeIndex].IsDst) { // found the next DST transition start time Dst = true; DstStartIndex = index; } else { index++; } } // find the next DST transition end time index while (Dst && index < typeOfLocalTime.Length) { int typeIndex = typeOfLocalTime[index]; if (typeIndex < transitionType.Length && !transitionType[typeIndex].IsDst) { // found the next DST transition end time Dst = false; DstEndIndex = index; } else { index++; } } // // construct the adjustment rule from the two indices // if (DstStartIndex >= 0) { DateTime startTransitionDate = dts[DstStartIndex]; DateTime endTransitionDate; if (DstEndIndex == -1) { // we found a DST start but no DST end; in this case use the // prior non-DST entry if it exists, else use the current entry for both start and end (e.g., zero daylightDelta) if (DstStartIndex > 0) { DstEndIndex = DstStartIndex - 1; } else { DstEndIndex = DstStartIndex; } endTransitionDate = DateTime.MaxValue; } else { endTransitionDate = dts[DstEndIndex]; } int dstStartTypeIndex = typeOfLocalTime[DstStartIndex]; int dstEndTypeIndex = typeOfLocalTime[DstEndIndex]; TimeSpan daylightBias = transitionType[dstStartTypeIndex].UtcOffset - transitionType[dstEndTypeIndex].UtcOffset; // TZif supports seconds-level granularity with offsets but TimeZoneInfo only supports minutes since it aligns // with DateTimeOffset, SQL Server, and the W3C XML Specification if (daylightBias.Ticks % TimeSpan.TicksPerMinute != 0) { daylightBias = new TimeSpan(daylightBias.Hours, daylightBias.Minutes, 0); } // // the normal case is less than 12 months between transition times. However places like America/Catamarca // have DST from 1946-1963 straight without a gap. In that case we need to create a series of Adjustment // Rules to fudge the multi-year DST period // if ((endTransitionDate - startTransitionDate).Ticks <= TimeSpan.TicksPerDay * 364) { TransitionTime dstStart; TransitionTime dstEnd; TimeSpan startTransitionOffset = (DstStartIndex > 0 ? transitionType[typeOfLocalTime[DstStartIndex - 1]].UtcOffset : transitionType[dstEndTypeIndex].UtcOffset); TimeSpan endTransitionOffset = (DstEndIndex > 0 ? transitionType[typeOfLocalTime[DstEndIndex - 1]].UtcOffset : transitionType[dstStartTypeIndex].UtcOffset); dstStart = TZif_CalculateTransitionTime(startTransitionDate, startTransitionOffset, transitionType[dstStartTypeIndex], StandardTime[dstStartTypeIndex], GmtTime[dstStartTypeIndex], out startDate); dstEnd = TZif_CalculateTransitionTime(endTransitionDate, endTransitionOffset, transitionType[dstEndTypeIndex], StandardTime[dstEndTypeIndex], GmtTime[dstEndTypeIndex], out endDate); // calculate the AdjustmentRule end date if (DstStartIndex >= DstEndIndex) { // we found a DST start but no DST end endDate = DateTime.MaxValue.Date; } AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(startDate, endDate, daylightBias, dstStart, dstEnd); rulesList.Add(r); } else { // create the multi-year DST rule series: // // For example America/Catamarca: // 1946-10-01T04:00:00.0000000Z {-03:00:00 DST=True} // 1963-10-01T03:00:00.0000000Z {-04:00:00 DST=False} // // gets converted into a series of overlapping 5/7month adjustment rules: // // [AdjustmentRule #0] // start rule // [1946/09/31 - 1947/06/15] // * starts 1 day prior to startTransitionDate // [start: 10/01 @4:00 ] // * N months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _end_ is outside the range // // [AdjustmentRule #1] // middle-year all-DST rule // [1947/06/16 - 1947/11/15] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * 5 months long, stopping at month 6 or 11 // [end : 12/15 ] // notice how the _start and end_ are outside the range // // [AdjustmentRule #2] // middle-year all-DST rule // [1947/11/16 - 1947/06/15] // * starts 1 day after last day in previous rule // [start: 10/01 ] // * 7 months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _start and end_ are outside the range // // ......................... // // [AdjustmentRule #N] // end rule // [1963/06/16 - 1946/10/02] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * N months long, stopping 1 day after endTransitionDate // [end : 10/01 ] // notice how the _start_ is outside the range // // create the first rule from N to either 06/15 or 11/15 TZif_CreateFirstMultiYearRule(ref rulesList, daylightBias, startTransitionDate, DstStartIndex, dstStartTypeIndex, dstEndTypeIndex, dts, transitionType, typeOfLocalTime, StandardTime, GmtTime); // create the filler rules TZif_CreateMiddleMultiYearRules(ref rulesList, daylightBias, endTransitionDate); // create the last rule TZif_CreateLastMultiYearRule(ref rulesList, daylightBias, endTransitionDate, DstStartIndex, dstStartTypeIndex, DstEndIndex, dstEndTypeIndex, dts, transitionType, typeOfLocalTime, StandardTime, GmtTime); } startIndex = index + 1; return(true); } // setup the start values for the next call to TZif_GenerateAdjustmentRule(...) startIndex = index + 1; return(false); // did not create a new AdjustmentRule }
private static void ParseRegTzi(List <AdjustmentRule> adjustmentRules, int start_year, int end_year, byte [] buffer) { //int standard_bias = BitConverter.ToInt32 (buffer, 4); /* not sure how to handle this */ int daylight_bias = BitConverter.ToInt32(buffer, 8); int standard_year = BitConverter.ToInt16(buffer, 12); int standard_month = BitConverter.ToInt16(buffer, 14); int standard_dayofweek = BitConverter.ToInt16(buffer, 16); int standard_day = BitConverter.ToInt16(buffer, 18); int standard_hour = BitConverter.ToInt16(buffer, 20); int standard_minute = BitConverter.ToInt16(buffer, 22); int standard_second = BitConverter.ToInt16(buffer, 24); int standard_millisecond = BitConverter.ToInt16(buffer, 26); int daylight_year = BitConverter.ToInt16(buffer, 28); int daylight_month = BitConverter.ToInt16(buffer, 30); int daylight_dayofweek = BitConverter.ToInt16(buffer, 32); int daylight_day = BitConverter.ToInt16(buffer, 34); int daylight_hour = BitConverter.ToInt16(buffer, 36); int daylight_minute = BitConverter.ToInt16(buffer, 38); int daylight_second = BitConverter.ToInt16(buffer, 40); int daylight_millisecond = BitConverter.ToInt16(buffer, 42); if (standard_month == 0 || daylight_month == 0) { return; } DateTime start_date; DateTime start_timeofday = new DateTime(1, 1, 1, daylight_hour, daylight_minute, daylight_second, daylight_millisecond); TransitionTime start_transition_time; if (daylight_year == 0) { start_date = new DateTime(start_year, 1, 1); start_transition_time = TransitionTime.CreateFloatingDateRule( start_timeofday, daylight_month, daylight_day, (DayOfWeek)daylight_dayofweek); } else { start_date = new DateTime(daylight_year, daylight_month, daylight_day, daylight_hour, daylight_minute, daylight_second, daylight_millisecond); start_transition_time = TransitionTime.CreateFixedDateRule( start_timeofday, daylight_month, daylight_day); } DateTime end_date; DateTime end_timeofday = new DateTime(1, 1, 1, standard_hour, standard_minute, standard_second, standard_millisecond); TransitionTime end_transition_time; if (standard_year == 0) { end_date = new DateTime(end_year, 12, 31); end_transition_time = TransitionTime.CreateFloatingDateRule( end_timeofday, standard_month, standard_day, (DayOfWeek)standard_dayofweek); } else { end_date = new DateTime(standard_year, standard_month, standard_day, standard_hour, standard_minute, standard_second, standard_millisecond); end_transition_time = TransitionTime.CreateFixedDateRule( end_timeofday, standard_month, standard_day); } TimeSpan daylight_delta = new TimeSpan(0, -daylight_bias, 0); adjustmentRules.Add(AdjustmentRule.CreateAdjustmentRule( start_date, end_date, daylight_delta, start_transition_time, end_transition_time)); }
private static TimeZoneInfo ParseTZBuffer(string id, byte [] buffer, int length) { //Reading the header. 4 bytes for magic, 16 are reserved int ttisgmtcnt = ReadBigEndianInt32(buffer, 20); int ttisstdcnt = ReadBigEndianInt32(buffer, 24); int leapcnt = ReadBigEndianInt32(buffer, 28); int timecnt = ReadBigEndianInt32(buffer, 32); int typecnt = ReadBigEndianInt32(buffer, 36); int charcnt = ReadBigEndianInt32(buffer, 40); if (length < 44 + timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisstdcnt + ttisgmtcnt) { throw new InvalidTimeZoneException(); } Dictionary <int, string> abbreviations = ParseAbbreviations(buffer, 44 + 4 * timecnt + timecnt + 6 * typecnt, charcnt); Dictionary <int, TimeType> time_types = ParseTimesTypes(buffer, 44 + 4 * timecnt + timecnt, typecnt, abbreviations); List <KeyValuePair <DateTime, TimeType> > transitions = ParseTransitions(buffer, 44, timecnt, time_types); if (time_types.Count == 0) { throw new InvalidTimeZoneException(); } if (time_types.Count == 1 && ((TimeType)time_types[0]).IsDst) { throw new InvalidTimeZoneException(); } TimeSpan baseUtcOffset = new TimeSpan(0); TimeSpan dstDelta = new TimeSpan(0); string standardDisplayName = null; string daylightDisplayName = null; bool dst_observed = false; DateTime dst_start = DateTime.MinValue; List <AdjustmentRule> adjustmentRules = new List <AdjustmentRule> (); for (int i = 0; i < transitions.Count; i++) { var pair = transitions [i]; DateTime ttime = pair.Key; TimeType ttype = pair.Value; if (!ttype.IsDst) { if (standardDisplayName != ttype.Name || baseUtcOffset.TotalSeconds != ttype.Offset) { standardDisplayName = ttype.Name; daylightDisplayName = null; baseUtcOffset = new TimeSpan(0, 0, ttype.Offset); adjustmentRules = new List <AdjustmentRule> (); dst_observed = false; } if (dst_observed) { //FIXME: check additional fields for this: //most of the transitions are expressed in GMT dst_start += baseUtcOffset; DateTime dst_end = ttime + baseUtcOffset + dstDelta; //some weird timezone (America/Phoenix) have end dates on Jan 1st if (dst_end.Date == new DateTime(dst_end.Year, 1, 1) && dst_end.Year > dst_start.Year) { dst_end -= new TimeSpan(24, 0, 0); } DateTime dateStart, dateEnd; if (dst_start.Month < 7) { dateStart = new DateTime(dst_start.Year, 1, 1); } else { dateStart = new DateTime(dst_start.Year, 7, 1); } if (dst_end.Month >= 7) { dateEnd = new DateTime(dst_end.Year, 12, 31); } else { dateEnd = new DateTime(dst_end.Year, 6, 30); } TransitionTime transition_start = TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1) + dst_start.TimeOfDay, dst_start.Month, dst_start.Day); TransitionTime transition_end = TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1) + dst_end.TimeOfDay, dst_end.Month, dst_end.Day); if (transition_start != transition_end) //y, that happened in Argentina in 1943-1946 { adjustmentRules.Add(AdjustmentRule.CreateAdjustmentRule(dateStart, dateEnd, dstDelta, transition_start, transition_end)); } } dst_observed = false; } else { if (daylightDisplayName != ttype.Name || dstDelta.TotalSeconds != ttype.Offset - baseUtcOffset.TotalSeconds) { daylightDisplayName = ttype.Name; dstDelta = new TimeSpan(0, 0, ttype.Offset) - baseUtcOffset; } dst_start = ttime; dst_observed = true; } } if (adjustmentRules.Count == 0) { TimeType t = (TimeType)time_types [0]; if (standardDisplayName == null) { standardDisplayName = t.Name; baseUtcOffset = new TimeSpan(0, 0, t.Offset); } return(CreateCustomTimeZone(id, baseUtcOffset, id, standardDisplayName)); } else { return(CreateCustomTimeZone(id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules(adjustmentRules).ToArray())); } }
private static TimeZoneInfo ParseTZBuffer(string id, byte[] buffer, int length) { int num = ReadBigEndianInt32(buffer, 20); int num2 = ReadBigEndianInt32(buffer, 24); int num3 = ReadBigEndianInt32(buffer, 28); int num4 = ReadBigEndianInt32(buffer, 32); int num5 = ReadBigEndianInt32(buffer, 36); int num6 = ReadBigEndianInt32(buffer, 40); if (length < 44 + num4 * 5 + num5 * 6 + num6 + num3 * 8 + num2 + num) { throw new InvalidTimeZoneException(); } Dictionary <int, string> abbreviations = ParseAbbreviations(buffer, 44 + 4 * num4 + num4 + 6 * num5, num6); Dictionary <int, TimeType> dictionary = ParseTimesTypes(buffer, 44 + 4 * num4 + num4, num5, abbreviations); List <KeyValuePair <DateTime, TimeType> > list = ParseTransitions(buffer, 44, num4, dictionary); if (dictionary.Count == 0) { throw new InvalidTimeZoneException(); } if (dictionary.Count == 1) { TimeType timeType = dictionary[0]; if (timeType.IsDst) { throw new InvalidTimeZoneException(); } } TimeSpan timeSpan = new TimeSpan(0L); TimeSpan timeSpan2 = new TimeSpan(0L); string text = null; string a = null; bool flag = false; DateTime d = DateTime.MinValue; List <AdjustmentRule> list2 = new List <AdjustmentRule>(); for (int i = 0; i < list.Count; i++) { KeyValuePair <DateTime, TimeType> keyValuePair = list[i]; DateTime key = keyValuePair.Key; TimeType value = keyValuePair.Value; if (!value.IsDst) { if (text != value.Name || timeSpan.TotalSeconds != (double)value.Offset) { text = value.Name; a = null; timeSpan = new TimeSpan(0, 0, value.Offset); list2 = new List <AdjustmentRule>(); flag = false; } if (flag) { d += timeSpan; DateTime d2 = key + timeSpan + timeSpan2; if (d2.Date == new DateTime(d2.Year, 1, 1) && d2.Year > d.Year) { d2 -= new TimeSpan(24, 0, 0); } DateTime dateStart = (d.Month < 7) ? new DateTime(d.Year, 1, 1) : new DateTime(d.Year, 7, 1); DateTime dateEnd = (d2.Month >= 7) ? new DateTime(d2.Year, 12, 31) : new DateTime(d2.Year, 6, 30); TransitionTime transitionTime = TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1) + d.TimeOfDay, d.Month, d.Day); TransitionTime transitionTime2 = TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1) + d2.TimeOfDay, d2.Month, d2.Day); if (transitionTime != transitionTime2) { list2.Add(AdjustmentRule.CreateAdjustmentRule(dateStart, dateEnd, timeSpan2, transitionTime, transitionTime2)); } } flag = false; } else { if (a != value.Name || timeSpan2.TotalSeconds != (double)value.Offset - timeSpan.TotalSeconds) { a = value.Name; timeSpan2 = new TimeSpan(0, 0, value.Offset) - timeSpan; } d = key; flag = true; } } if (list2.Count == 0) { TimeType timeType2 = dictionary[0]; if (text == null) { text = timeType2.Name; timeSpan = new TimeSpan(0, 0, timeType2.Offset); } return(CreateCustomTimeZone(id, timeSpan, id, text)); } return(CreateCustomTimeZone(id, timeSpan, id, text, a, ValidateRules(list2).ToArray())); }
/// <summary> /// Helper function to read an AdjustmentRule token. /// </summary> private AdjustmentRule GetNextAdjustmentRuleValue(bool canEndWithoutSeparator) { // first verify the internal state of the object if (_state == State.EndOfLine) { if (canEndWithoutSeparator) { return(null); } else { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData")); } } if (_currentTokenStartIndex < 0 || _currentTokenStartIndex >= _serializedText.Length) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData")); } // check to see if the very first token we see is the separator if (_serializedText[_currentTokenStartIndex] == Sep) { return(null); } // verify the current token is a left-hand-side marker ("[") if (_serializedText[_currentTokenStartIndex] != Lhs) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData")); } _currentTokenStartIndex++; DateTime dateStart = GetNextDateTimeValue(false, DateTimeFormat); DateTime dateEnd = GetNextDateTimeValue(false, DateTimeFormat); TimeSpan daylightDelta = GetNextTimeSpanValue(canEndWithoutSeparator: false); TransitionTime daylightStart = GetNextTransitionTimeValue(canEndWithoutSeparator: false); TransitionTime daylightEnd = GetNextTransitionTimeValue(canEndWithoutSeparator: false); TimeSpan baseUtcOffsetDelta = TimeSpan.Zero; int noDaylightTransitions = 0; // verify that the string is now at the right-hand-side marker ("]") ... if (_state == State.EndOfLine || _currentTokenStartIndex >= _serializedText.Length) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData")); } // Check if we have baseUtcOffsetDelta in the serialized string and then deserialize it if ((_serializedText[_currentTokenStartIndex] >= '0' && _serializedText[_currentTokenStartIndex] <= '9') || _serializedText[_currentTokenStartIndex] == '-' || _serializedText[_currentTokenStartIndex] == '+') { baseUtcOffsetDelta = GetNextTimeSpanValue(canEndWithoutSeparator: false); } // Check if we have NoDaylightTransitions in the serialized string and then deserialize it if ((_serializedText[_currentTokenStartIndex] >= '0' && _serializedText[_currentTokenStartIndex] <= '1')) { noDaylightTransitions = GetNextInt32Value(canEndWithoutSeparator: false); } if (_state == State.EndOfLine || _currentTokenStartIndex >= _serializedText.Length) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData")); } if (_serializedText[_currentTokenStartIndex] != Rhs) { // skip ahead of any "v.Next" data at the end of the AdjustmentRule // // FUTURE: if the serialization format is extended in the future then this // code section will need to be changed to read the new fields rather // than just skipping the data at the end of the [AdjustmentRule]. SkipVersionNextDataFields(1); } else { _currentTokenStartIndex++; } // create the AdjustmentRule from the deserialized fields ... AdjustmentRule rule; try { rule = AdjustmentRule.CreateAdjustmentRule(dateStart, dateEnd, daylightDelta, daylightStart, daylightEnd, baseUtcOffsetDelta, noDaylightTransitions > 0); } catch (ArgumentException e) { throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e); } // finally set the state to either EndOfLine or StartOfToken for the next caller if (_currentTokenStartIndex >= _serializedText.Length) { _state = State.EndOfLine; } else { _state = State.StartOfToken; } return(rule); }