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"));
            }
        }
Exemple #2
0
        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);
                }
            }
        }
Exemple #3
0
        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));
        }
Exemple #5
0
        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);
        }
Exemple #6
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)));
        }
Exemple #7
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()));
        }
Exemple #8
0
        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);
            }
        }
Exemple #9
0
        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
        }
Exemple #10
0
        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));
        }
Exemple #11
0
        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()));
            }
        }
Exemple #12
0
        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);
            }