Exemple #1
0
        public TimeSpan GetUtcOffset(DateTime dateTime)
        {
            if (IsDaylightSavingTime(dateTime))
            {
                AdjustmentRule rule = GetApplicableRule(dateTime);
                if (rule != null)
                {
                    return(BaseUtcOffset + rule.DaylightDelta);
                }
            }

            return(BaseUtcOffset);
        }
Exemple #2
0
            public OffsetAndRule GetOneYearLocalFromUtc(int year)
            {
                OffsetAndRule oneYearLocFromUtc = _oneYearLocalFromUtc;

                if (oneYearLocFromUtc == null || oneYearLocFromUtc.Year != year)
                {
                    TimeZoneInfo   currentYear = GetCurrentOneYearLocal();
                    AdjustmentRule rule        = currentYear._adjustmentRules == null ? null : currentYear._adjustmentRules[0];
                    oneYearLocFromUtc    = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule);
                    _oneYearLocalFromUtc = oneYearLocFromUtc;
                }
                return(oneYearLocFromUtc);
            }
Exemple #3
0
        static List <AdjustmentRule> ValidateRules(List <AdjustmentRule> adjustmentRules)
        {
            AdjustmentRule prev = null;

            foreach (AdjustmentRule current in adjustmentRules.ToArray())
            {
                if (prev != null && prev.DateEnd > current.DateStart)
                {
                    adjustmentRules.Remove(current);
                }
                prev = current;
            }
            return(adjustmentRules);
        }
Exemple #4
0
        public TimeSpan[] GetAmbiguousTimeOffsets(DateTime dateTime)
        {
            if (!IsAmbiguousTime(dateTime))
            {
                throw new ArgumentException("dateTime is not an ambiguous time");
            }
            AdjustmentRule applicableRule = GetApplicableRule(dateTime);

            return(new TimeSpan[2]
            {
                baseUtcOffset,
                baseUtcOffset + applicableRule.DaylightDelta
            });
        }
Exemple #5
0
        private static List <AdjustmentRule> ValidateRules(List <AdjustmentRule> adjustmentRules)
        {
            AdjustmentRule adjustmentRule = null;

            AdjustmentRule[] array = adjustmentRules.ToArray();
            foreach (AdjustmentRule adjustmentRule2 in array)
            {
                if (adjustmentRule != null && adjustmentRule.DateEnd > adjustmentRule2.DateStart)
                {
                    adjustmentRules.Remove(adjustmentRule2);
                }
                adjustmentRule = adjustmentRule2;
            }
            return(adjustmentRules);
        }
Exemple #6
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()));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="LegacyAvailabilityTimeZone"/> class.
        /// </summary>
        /// <param name="timeZoneInfo">The time zone used to initialize this instance.</param>
        internal LegacyAvailabilityTimeZone(TimeZoneInfo timeZoneInfo)
            : this()
        {
            // Availability uses the opposite sign for the bias, e.g. if TimeZoneInfo.BaseUtcOffset = 480 than
            // SerializedTimeZone.Bias must be -480.
            this.bias = -timeZoneInfo.BaseUtcOffset;

            // To convert TimeZoneInfo into SerializableTimeZone, we need two time changes: one to Standard
            // time, the other to Daylight time. TimeZoneInfo holds a list of adjustment rules that represent
            // the different rules that govern time changes over the years. We need to grab one of those rules
            // to initialize this instance.
            AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRulesEx();

            if (adjustmentRules.Length == 0)
            {
                // If there are no adjustment rules (which is the case for UTC), we have to come up with two
                // dummy time changes which both have a delta of zero and happen at two hard coded dates. This
                // simulates a time zone in which there are no time changes.
                this.daylightTime              = new LegacyAvailabilityTimeZoneTime();
                this.daylightTime.Delta        = TimeSpan.Zero;
                this.daylightTime.DayOrder     = 1;
                this.daylightTime.DayOfTheWeek = DayOfTheWeek.Sunday;
                this.daylightTime.Month        = 10;
                this.daylightTime.TimeOfDay    = TimeSpan.FromHours(2);
                this.daylightTime.Year         = 0;

                this.standardTime              = new LegacyAvailabilityTimeZoneTime();
                this.standardTime.Delta        = TimeSpan.Zero;
                this.standardTime.DayOrder     = 1;
                this.standardTime.DayOfTheWeek = DayOfTheWeek.Sunday;
                this.standardTime.Month        = 3;
                this.standardTime.TimeOfDay    = TimeSpan.FromHours(2);
                this.daylightTime.Year         = 0;
            }
            else
            {
                // When there is at least one adjustment rule, we need to grab the last one which is the
                // one that currently applies (TimeZoneInfo stores adjustment rules sorted from oldest to
                // most recent).
                AdjustmentRule currentRule = adjustmentRules[adjustmentRules.Length - 1];

                this.standardTime = new LegacyAvailabilityTimeZoneTime(currentRule.DaylightTransitionEnd, TimeSpan.Zero);

                // Again, TimeZoneInfo and SerializableTime use opposite signs for bias.
                this.daylightTime = new LegacyAvailabilityTimeZoneTime(currentRule.DaylightTransitionStart, -currentRule.DaylightDelta);
            }
        }
Exemple #8
0
        public static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone)
        {
            if (sourceTimeZone == null)
            {
                throw new ArgumentNullException("sourceTimeZone");
            }

            if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone != TimeZoneInfo.Utc)
            {
                throw new ArgumentException("Kind propery of dateTime is Utc but the sourceTimeZone does not equal TimeZoneInfo.Utc");
            }

            if (dateTime.Kind == DateTimeKind.Local && sourceTimeZone != TimeZoneInfo.Local)
            {
                throw new ArgumentException("Kind propery of dateTime is Local but the sourceTimeZone does not equal TimeZoneInfo.Local");
            }

            if (sourceTimeZone.IsInvalidTime(dateTime))
            {
                throw new ArgumentException("dateTime parameter is an invalid time");
            }

            if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone == TimeZoneInfo.Utc)
            {
                return(dateTime);
            }

            if (dateTime.Kind == DateTimeKind.Utc)
            {
                return(dateTime);
            }

            if (dateTime.Kind == DateTimeKind.Local)
            {
                return(ConvertTimeToUtc(dateTime));
            }

            if (sourceTimeZone.IsAmbiguousTime(dateTime) || !sourceTimeZone.IsDaylightSavingTime(dateTime))
            {
                return(DateTime.SpecifyKind(dateTime - sourceTimeZone.BaseUtcOffset, DateTimeKind.Utc));
            }
            else
            {
                AdjustmentRule rule = sourceTimeZone.GetApplicableRule(dateTime);
                return(DateTime.SpecifyKind(dateTime - sourceTimeZone.BaseUtcOffset - rule.DaylightDelta, DateTimeKind.Utc));
            }
        }
        /// <summary>
        /// Initializes this transition group based on the specified asjustment rule.
        /// </summary>
        /// <param name="adjustmentRule">The adjustment rule to initialize from.</param>
        /// <param name="standardPeriod">A reference to the pre-created standard period.</param>
        internal virtual void InitializeFromAdjustmentRule(AdjustmentRule adjustmentRule, TimeZonePeriod standardPeriod)
        {
            if (adjustmentRule.DaylightDelta.TotalSeconds == 0)
            {
                // If the time zone info doesn't support Daylight Saving Time, we just need to
                // create one transition to one group with one transition to the standard period.
                TimeZonePeriod standardPeriodToSet = new TimeZonePeriod();
                standardPeriodToSet.Id   = $"{standardPeriod.Id}/{adjustmentRule.DateStart:yyyyMMdd}";
                standardPeriodToSet.Name = standardPeriod.Name;
                standardPeriodToSet.Bias = standardPeriod.Bias;
                this.timeZoneDefinition.Periods.AddOrUpdate(standardPeriodToSet.Id, standardPeriodToSet);

                this.transitionToStandard = new TimeZoneTransition(this.timeZoneDefinition, standardPeriodToSet);
                this.transitions.Add(this.transitionToStandard);
            }
            else
            {
                TimeZonePeriod daylightPeriod = new TimeZonePeriod();

                // Generate an Id of the form "Daylight/2008"
                daylightPeriod.Id   = $"{TimeZonePeriod.DaylightPeriodId}/{adjustmentRule.DateStart:yyyyMMdd}";
                daylightPeriod.Name = TimeZonePeriod.DaylightPeriodName;
                daylightPeriod.Bias = standardPeriod.Bias - adjustmentRule.DaylightDelta;

                this.timeZoneDefinition.Periods.AddOrUpdate(daylightPeriod.Id, daylightPeriod);

                this.transitionToDaylight = TimeZoneTransition.CreateTimeZoneTransition(
                    this.timeZoneDefinition,
                    daylightPeriod,
                    adjustmentRule.DaylightTransitionStart);

                TimeZonePeriod standardPeriodToSet = new TimeZonePeriod();
                standardPeriodToSet.Id   = $"{standardPeriod.Id}/{adjustmentRule.DateStart:yyyyMMdd}";
                standardPeriodToSet.Name = standardPeriod.Name;
                standardPeriodToSet.Bias = standardPeriod.Bias;
                this.timeZoneDefinition.Periods.AddOrUpdate(standardPeriodToSet.Id, standardPeriodToSet);

                this.transitionToStandard = TimeZoneTransition.CreateTimeZoneTransition(
                    this.timeZoneDefinition,
                    standardPeriodToSet,
                    adjustmentRule.DaylightTransitionEnd);

                this.transitions.Add(this.transitionToDaylight);
                this.transitions.Add(this.transitionToStandard);
            }
        }
Exemple #10
0
        public bool IsDaylightSavingTime(DateTime dateTime)
        {
            if (dateTime.Kind == DateTimeKind.Local && IsInvalidTime(dateTime))
            {
                throw new ArgumentException("dateTime is invalid and Kind is Local");
            }

            if (this == TimeZoneInfo.Utc)
            {
                return(false);
            }

            if (!SupportsDaylightSavingTime)
            {
                return(false);
            }
            //FIXME: do not rely on DateTime implementation !
            if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local)
            {
                return(dateTime.IsDaylightSavingTime());
            }

            //FIXME: do not rely on DateTime implementation !
            if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc)
            {
                return(IsDaylightSavingTime(DateTime.SpecifyKind(dateTime.ToUniversalTime(), DateTimeKind.Utc)));
            }

            AdjustmentRule rule = GetApplicableRule(dateTime.Date);

            if (rule == null)
            {
                return(false);
            }

            DateTime DST_start = TransitionPoint(rule.DaylightTransitionStart, dateTime.Year);
            DateTime DST_end   = TransitionPoint(rule.DaylightTransitionEnd, dateTime.Year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1));

            if (dateTime.Kind == DateTimeKind.Utc)
            {
                DST_start -= BaseUtcOffset;
                DST_end   -= (BaseUtcOffset + rule.DaylightDelta);
            }

            return(dateTime >= DST_start && dateTime < DST_end);
        }
Exemple #11
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 #12
0
        public bool IsInvalidTime(DateTime dateTime)
        {
            if (dateTime.Kind == DateTimeKind.Utc)
            {
                return(false);
            }
            if (dateTime.Kind == DateTimeKind.Local && this != Local)
            {
                return(false);
            }
            AdjustmentRule applicableRule = GetApplicableRule(dateTime);
            DateTime       dateTime2      = TransitionPoint(applicableRule.DaylightTransitionStart, dateTime.Year);

            if (dateTime >= dateTime2 && dateTime < dateTime2 + applicableRule.DaylightDelta)
            {
                return(true);
            }
            return(false);
        }
Exemple #13
0
        public TimeSpan [] GetAmbiguousTimeOffsets(DateTime dateTime)
        {
            if (!IsAmbiguousTime(dateTime))
            {
                throw new ArgumentException("dateTime is not an ambiguous time");
            }

            AdjustmentRule rule = GetApplicableRule(dateTime);

            if (rule != null)
            {
                return new TimeSpan[] { baseUtcOffset, baseUtcOffset + rule.DaylightDelta }
            }
            ;
            else
            {
                return new TimeSpan[] { baseUtcOffset, baseUtcOffset }
            };
        }
Exemple #14
0
        public static DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone)
        {
            if (destinationTimeZone == null)
            {
                throw new ArgumentNullException("destinationTimeZone");
            }

            var            utcDateTime = dateTimeOffset.UtcDateTime;
            AdjustmentRule rule        = destinationTimeZone.GetApplicableRule(utcDateTime);

            if (rule != null && destinationTimeZone.IsDaylightSavingTime(utcDateTime))
            {
                var offset = destinationTimeZone.BaseUtcOffset + rule.DaylightDelta;
                return(new DateTimeOffset(DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified) + offset, offset));
            }
            else
            {
                return(new DateTimeOffset(DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified) + destinationTimeZone.BaseUtcOffset, destinationTimeZone.BaseUtcOffset));
            }
        }
Exemple #15
0
 /// <summary>
 /// Normalize adjustment rule offset so that it is within valid range
 /// This method should not be called at all but is here in case something changes in the future
 /// or if really old time zones are present on the OS (no combination is known at the moment)
 /// </summary>
 private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, [NotNull] ref AdjustmentRule adjustmentRule)
 {
     // Certain time zones such as:
     //       Time Zone  start date  end date    offset
     // -----------------------------------------------------
     // America/Yakutat  0001-01-01  1867-10-18   14:41:00
     // America/Yakutat  1867-10-18  1900-08-20   14:41:00
     // America/Sitka    0001-01-01  1867-10-18   14:58:00
     // America/Sitka    1867-10-18  1900-08-20   14:58:00
     // Asia/Manila      0001-01-01  1844-12-31  -15:56:00
     // Pacific/Guam     0001-01-01  1845-01-01  -14:21:00
     // Pacific/Saipan   0001-01-01  1845-01-01  -14:21:00
     //
     // have larger offset than currently supported by framework.
     // If for whatever reason we find that time zone exceeding max
     // offset of 14h this function will truncate it to the max valid offset.
     // Updating max offset may cause problems with interacting with SQL server
     // which uses SQL DATETIMEOFFSET field type which was originally designed to be
     // bit-for-bit compatible with DateTimeOffset.
     throw new NotImplementedException();
 }
Exemple #16
0
        private DateTime ConvertTimeFromUtc(DateTime dateTime)
        {
            if (dateTime.Kind == DateTimeKind.Local)
            {
                throw new ArgumentException("Kind property of dateTime is Local");
            }
            if (this == Utc)
            {
                return(DateTime.SpecifyKind(dateTime, DateTimeKind.Utc));
            }
            if (this == Local)
            {
                return(DateTime.SpecifyKind(dateTime.ToLocalTime(), DateTimeKind.Unspecified));
            }
            AdjustmentRule applicableRule = GetApplicableRule(dateTime);

            if (IsDaylightSavingTime(DateTime.SpecifyKind(dateTime, DateTimeKind.Utc)))
            {
                return(DateTime.SpecifyKind(dateTime + BaseUtcOffset + applicableRule.DaylightDelta, DateTimeKind.Unspecified));
            }
            return(DateTime.SpecifyKind(dateTime + BaseUtcOffset, DateTimeKind.Unspecified));
        }
Exemple #17
0
        public bool IsDaylightSavingTime(DateTime dateTime)
        {
            if (dateTime.Kind == DateTimeKind.Local && IsInvalidTime(dateTime))
            {
                throw new ArgumentException("dateTime is invalid and Kind is Local");
            }
            if (this == Utc)
            {
                return(false);
            }
            if (!SupportsDaylightSavingTime)
            {
                return(false);
            }
            if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == Local)
            {
                return(dateTime.IsDaylightSavingTime());
            }
            if (dateTime.Kind == DateTimeKind.Local && this != Utc)
            {
                return(IsDaylightSavingTime(DateTime.SpecifyKind(dateTime.ToUniversalTime(), DateTimeKind.Utc)));
            }
            AdjustmentRule applicableRule = GetApplicableRule(dateTime.Date);

            if (applicableRule == null)
            {
                return(false);
            }
            DateTime dateTime2 = TransitionPoint(applicableRule.DaylightTransitionStart, dateTime.Year);
            DateTime dateTime3 = TransitionPoint(applicableRule.DaylightTransitionEnd, dateTime.Year + ((applicableRule.DaylightTransitionStart.Month >= applicableRule.DaylightTransitionEnd.Month) ? 1 : 0));

            if (dateTime.Kind == DateTimeKind.Utc)
            {
                dateTime2 -= BaseUtcOffset;
                dateTime3 -= BaseUtcOffset + applicableRule.DaylightDelta;
            }
            return(dateTime >= dateTime2 && dateTime < dateTime3);
        }
        /// <summary>
        /// Initializes this transition group based on the specified asjustment rule.
        /// </summary>
        /// <param name="adjustmentRule">The adjustment rule to initialize from.</param>
        /// <param name="standardPeriod">A reference to the pre-created standard period.</param>
        internal virtual void InitializeFromAdjustmentRule(AdjustmentRule adjustmentRule, TimeZonePeriod standardPeriod)
        {
            TimeZonePeriod daylightPeriod = new TimeZonePeriod();

            // Generate an Id of the form "Daylight/2008"
            daylightPeriod.Id = string.Format(
                "{0}/{1}",
                TimeZonePeriod.DaylightPeriodId,
                adjustmentRule.DateStart.Year);
            daylightPeriod.Name = TimeZonePeriod.DaylightPeriodName;
            daylightPeriod.Bias = standardPeriod.Bias - adjustmentRule.DaylightDelta;

            this.timeZoneDefinition.Periods.Add(daylightPeriod.Id, daylightPeriod);

            this.transitionToDaylight = TimeZoneTransition.CreateTimeZoneTransition(
                this.timeZoneDefinition,
                daylightPeriod,
                adjustmentRule.DaylightTransitionStart);

            TimeZonePeriod standardPeriodToSet = new TimeZonePeriod();

            standardPeriodToSet.Id = string.Format(
                "{0}/{1}",
                standardPeriod.Id,
                adjustmentRule.DateStart.Year);
            standardPeriodToSet.Name = standardPeriod.Name;
            standardPeriodToSet.Bias = standardPeriod.Bias;
            this.timeZoneDefinition.Periods.Add(standardPeriodToSet.Id, standardPeriodToSet);

            this.transitionToStandard = TimeZoneTransition.CreateTimeZoneTransition(
                this.timeZoneDefinition,
                standardPeriodToSet,
                adjustmentRule.DaylightTransitionEnd);

            this.transitions.Add(this.transitionToDaylight);
            this.transitions.Add(this.transitionToStandard);
        }
Exemple #19
0
        public bool IsInvalidTime(DateTime dateTime)
        {
            if (dateTime.Kind == DateTimeKind.Utc)
            {
                return(false);
            }
            if (dateTime.Kind == DateTimeKind.Local && this != Local)
            {
                return(false);
            }

            AdjustmentRule rule = GetApplicableRule(dateTime);

            if (rule != null)
            {
                DateTime tpoint = TransitionPoint(rule.DaylightTransitionStart, dateTime.Year);
                if (dateTime >= tpoint && dateTime < tpoint + rule.DaylightDelta)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #20
0
        // -------- SECTION: constructors -----------------*
        // 
        // TimeZoneInfo -
        //
        // private ctor
        //
        private unsafe TimeZoneInfo(TIME_ZONE_INFORMATION zone, Boolean dstDisabled)
        {
            if (String.IsNullOrEmpty(new String(zone.StandardName)))
            {
                _id = c_localId;  // the ID must contain at least 1 character - initialize _id to "Local"
            }
            else
            {
                _id = new String(zone.StandardName);
            }
            _baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0);

            if (!dstDisabled)
            {
                // only create the adjustment rule if DST is enabled
                REGISTRY_TIME_ZONE_INFORMATION regZone = new REGISTRY_TIME_ZONE_INFORMATION(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 = new String(zone.StandardName);
            _standardDisplayName = new String(zone.StandardName);
            _daylightDisplayName = new String(zone.DaylightName);
        }
 public static (DateTime from, DateTime to) DaylightSaving(this AdjustmentRule adjustmentRule)
 {
     return(adjustmentRule.DaylightStart(), adjustmentRule.DaylightEnd());
 }
Exemple #22
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));
        }
 public static DateTime DaylightStart(this AdjustmentRule adjustmentRule)
 {
     return(adjustmentRule.DaylightTransitionStart.ToDateTime(adjustmentRule.DateStart.Year)); //.AddSeconds(-1);
 }
Exemple #24
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 #25
0
        //
        // TryCreateAdjustmentRules -
        //
        // Helper function that takes 
        //  1. a string representing a <time_zone_name> registry key name
        //  2. a RegistryTimeZoneInformation struct containing the default rule
        //  3. an AdjustmentRule[] out-parameter
        // 
        // returns 
        //     TimeZoneInfoResult.InvalidTimeZoneException,
        //     TimeZoneInfoResult.TimeZoneNotFoundException,
        //     TimeZoneInfoResult.Success
        //                             
        // Optional, Dynamic Time Zone Registry Data
        // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
        //
        // HKLM 
        //     Software 
        //         Microsoft 
        //             Windows NT 
        //                 CurrentVersion 
        //                     Time Zones 
        //                         <time_zone_name>
        //                             Dynamic DST
        // * "FirstEntry" REG_DWORD "1980"
        //                           First year in the table. If the current year is less than this value,
        //                           this entry will be used for DST boundaries
        // * "LastEntry"  REG_DWORD "2038"
        //                           Last year in the table. If the current year is greater than this value,
        //                           this entry will be used for DST boundaries"
        // * "<year1>"    REG_BINARY REG_TZI_FORMAT
        //                       See REGISTRY_TIME_ZONE_INFORMATION
        // * "<year2>"    REG_BINARY REG_TZI_FORMAT 
        //                       See REGISTRY_TIME_ZONE_INFORMATION
        // * "<year3>"    REG_BINARY REG_TZI_FORMAT
        //                       See REGISTRY_TIME_ZONE_INFORMATION
        //
        // This method expects that its caller has already Asserted RegistryPermission.Read
        //
        private static bool TryCreateAdjustmentRules(string id, REGISTRY_TIME_ZONE_INFORMATION defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset)
        {
            e = null;

            try
            {
                using (RegistryKey dynamicKey = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE).OpenSubKey(
                                   c_timeZonesRegistryHive + "\\" + id + "\\Dynamic DST",
                                   false
                                   ))
                {
                    if (dynamicKey == null)
                    {
                        AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(
                                              defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);

                        if (rule == null)
                        {
                            rules = null;
                        }
                        else
                        {
                            rules = new AdjustmentRule[1];
                            rules[0] = rule;
                        }

                        return true;
                    }

                    //
                    // loop over all of the "<time_zone_name>\Dynamic DST" hive entries
                    //
                    // read FirstEntry  {MinValue      - (year1, 12, 31)}
                    // read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)}
                    // read LastEntry   {(yearN, 1, 1) - MaxValue       }

                    // read the FirstEntry and LastEntry key values (ex: "1980", "2038")
                    Int32 first = (Int32)dynamicKey.GetValue(c_firstEntryValue, -1, RegistryValueOptions.None);
                    Int32 last = (Int32)dynamicKey.GetValue(c_lastEntryValue, -1, RegistryValueOptions.None);

                    if (first == -1 || last == -1 || first > last)
                    {
                        rules = null;
                        return false;
                    }

                    // read the first year entry
                    REGISTRY_TIME_ZONE_INFORMATION dtzi;
                    Byte[] regValue = dynamicKey.GetValue(first.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
                    if (regValue == null || regValue.Length != c_regByteLength)
                    {
                        rules = null;
                        return false;
                    }
                    dtzi = new REGISTRY_TIME_ZONE_INFORMATION(regValue);

                    if (first == last)
                    {
                        // there is just 1 dynamic rule for this time zone.
                        AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);

                        if (rule == null)
                        {
                            rules = null;
                        }
                        else
                        {
                            rules = new AdjustmentRule[1];
                            rules[0] = rule;
                        }

                        return true;
                    }

                    List<AdjustmentRule> rulesList = new List<AdjustmentRule>(1);

                    // there are more than 1 dynamic rules for this time zone.
                    AdjustmentRule firstRule = CreateAdjustmentRuleFromTimeZoneInformation(
                                              dtzi,
                                              DateTime.MinValue.Date,        // MinValue
                                              new DateTime(first, 12, 31),   // December 31, <FirstYear>
                                              defaultBaseUtcOffset);
                    if (firstRule != null)
                    {
                        rulesList.Add(firstRule);
                    }

                    // read the middle year entries
                    for (Int32 i = first + 1; i < last; i++)
                    {
                        regValue = dynamicKey.GetValue(i.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
                        if (regValue == null || regValue.Length != c_regByteLength)
                        {
                            rules = null;
                            return false;
                        }
                        dtzi = new REGISTRY_TIME_ZONE_INFORMATION(regValue);
                        AdjustmentRule middleRule = CreateAdjustmentRuleFromTimeZoneInformation(
                                                  dtzi,
                                                  new DateTime(i, 1, 1),    // January  01, <Year>
                                                  new DateTime(i, 12, 31),  // December 31, <Year>
                                                  defaultBaseUtcOffset);
                        if (middleRule != null)
                        {
                            rulesList.Add(middleRule);
                        }
                    }
                    // read the last year entry
                    regValue = dynamicKey.GetValue(last.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
                    dtzi = new REGISTRY_TIME_ZONE_INFORMATION(regValue);
                    if (regValue == null || regValue.Length != c_regByteLength)
                    {
                        rules = null;
                        return false;
                    }
                    AdjustmentRule lastRule = CreateAdjustmentRuleFromTimeZoneInformation(
                                              dtzi,
                                              new DateTime(last, 1, 1),    // January  01, <LastYear>
                                              DateTime.MaxValue.Date,      // MaxValue
                                              defaultBaseUtcOffset);
                    if (lastRule != null)
                    {
                        rulesList.Add(lastRule);
                    }

                    // convert the ArrayList to an AdjustmentRule array
                    rules = rulesList.ToArray();
                    if (rules != null && rules.Length == 0)
                    {
                        rules = null;
                    }
                } // end of: using (RegistryKey dynamicKey...
            }
            catch (InvalidCastException ex)
            {
                // one of the RegistryKey.GetValue calls could not be cast to an expected value type
                rules = null;
                e = ex;
                return false;
            }
            catch (ArgumentOutOfRangeException ex)
            {
                rules = null;
                e = ex;
                return false;
            }
            catch (ArgumentException ex)
            {
                rules = null;
                e = ex;
                return false;
            }
            return true;
        }
Exemple #26
0
        /// <summary>
        /// Helper function that takes:
        ///  1. A string representing a <time_zone_name> registry key name.
        ///  2. A RegistryTimeZoneInformation struct containing the default rule.
        ///  3. An AdjustmentRule[] out-parameter.
        /// </summary>
        private static bool TryCreateAdjustmentRules(string id, Win32Native.RegistryTimeZoneInformation defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset)
        {
            e = null;

            try
            {
                // Optional, Dynamic Time Zone Registry Data
                // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                //
                // HKLM
                //     Software
                //         Microsoft
                //             Windows NT
                //                 CurrentVersion
                //                     Time Zones
                //                         <time_zone_name>
                //                             Dynamic DST
                // * "FirstEntry" REG_DWORD "1980"
                //                           First year in the table. If the current year is less than this value,
                //                           this entry will be used for DST boundaries
                // * "LastEntry"  REG_DWORD "2038"
                //                           Last year in the table. If the current year is greater than this value,
                //                           this entry will be used for DST boundaries"
                // * "<year1>"    REG_BINARY REG_TZI_FORMAT
                //                       See Win32Native.RegistryTimeZoneInformation
                // * "<year2>"    REG_BINARY REG_TZI_FORMAT
                //                       See Win32Native.RegistryTimeZoneInformation
                // * "<year3>"    REG_BINARY REG_TZI_FORMAT
                //                       See Win32Native.RegistryTimeZoneInformation
                //
                using (RegistryKey dynamicKey = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id + "\\Dynamic DST", writable: false))
                {
                    if (dynamicKey == null)
                    {
                        AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(
                            defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
                        rules = rule == null ? null : new[] { rule };
                        return(true);
                    }

                    //
                    // loop over all of the "<time_zone_name>\Dynamic DST" hive entries
                    //
                    // read FirstEntry  {MinValue      - (year1, 12, 31)}
                    // read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)}
                    // read LastEntry   {(yearN, 1, 1) - MaxValue       }

                    // read the FirstEntry and LastEntry key values (ex: "1980", "2038")
                    int first = (int)dynamicKey.GetValue(FirstEntryValue, -1, RegistryValueOptions.None);
                    int last  = (int)dynamicKey.GetValue(LastEntryValue, -1, RegistryValueOptions.None);

                    if (first == -1 || last == -1 || first > last)
                    {
                        rules = null;
                        return(false);
                    }

                    // read the first year entry
                    Win32Native.RegistryTimeZoneInformation dtzi;
                    byte[] regValue = dynamicKey.GetValue(first.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
                    if (regValue == null || regValue.Length != RegByteLength)
                    {
                        rules = null;
                        return(false);
                    }
                    dtzi = new Win32Native.RegistryTimeZoneInformation(regValue);

                    if (first == last)
                    {
                        // there is just 1 dynamic rule for this time zone.
                        AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
                        rules = rule == null ? null : new[] { rule };
                        return(true);
                    }

                    List <AdjustmentRule> rulesList = new List <AdjustmentRule>(1);

                    // there are more than 1 dynamic rules for this time zone.
                    AdjustmentRule firstRule = CreateAdjustmentRuleFromTimeZoneInformation(
                        dtzi,
                        DateTime.MinValue.Date,        // MinValue
                        new DateTime(first, 12, 31),   // December 31, <FirstYear>
                        defaultBaseUtcOffset);

                    if (firstRule != null)
                    {
                        rulesList.Add(firstRule);
                    }

                    // read the middle year entries
                    for (int i = first + 1; i < last; i++)
                    {
                        regValue = dynamicKey.GetValue(i.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
                        if (regValue == null || regValue.Length != RegByteLength)
                        {
                            rules = null;
                            return(false);
                        }
                        dtzi = new Win32Native.RegistryTimeZoneInformation(regValue);
                        AdjustmentRule middleRule = CreateAdjustmentRuleFromTimeZoneInformation(
                            dtzi,
                            new DateTime(i, 1, 1),    // January  01, <Year>
                            new DateTime(i, 12, 31),  // December 31, <Year>
                            defaultBaseUtcOffset);

                        if (middleRule != null)
                        {
                            rulesList.Add(middleRule);
                        }
                    }

                    // read the last year entry
                    regValue = dynamicKey.GetValue(last.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
                    dtzi     = new Win32Native.RegistryTimeZoneInformation(regValue);
                    if (regValue == null || regValue.Length != RegByteLength)
                    {
                        rules = null;
                        return(false);
                    }
                    AdjustmentRule lastRule = CreateAdjustmentRuleFromTimeZoneInformation(
                        dtzi,
                        new DateTime(last, 1, 1),    // January  01, <LastYear>
                        DateTime.MaxValue.Date,      // MaxValue
                        defaultBaseUtcOffset);

                    if (lastRule != null)
                    {
                        rulesList.Add(lastRule);
                    }

                    // convert the ArrayList to an AdjustmentRule array
                    rules = rulesList.ToArray();
                    if (rules != null && rules.Length == 0)
                    {
                        rules = null;
                    }
                } // end of: using (RegistryKey dynamicKey...
            }
            catch (InvalidCastException ex)
            {
                // one of the RegistryKey.GetValue calls could not be cast to an expected value type
                rules = null;
                e     = ex;
                return(false);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                rules = null;
                e     = ex;
                return(false);
            }
            catch (ArgumentException ex)
            {
                rules = null;
                e     = ex;
                return(false);
            }
            return(true);
        }
		bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year)
		{
			DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year);
			DateTime DST_end = TransitionPoint (rule.DaylightTransitionEnd, year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1));
			if (dateTime.Kind == DateTimeKind.Utc) {
				DST_start -= BaseUtcOffset;
				DST_end -= (BaseUtcOffset + rule.DaylightDelta);
			}

			return (dateTime >= DST_start && dateTime < DST_end);
		}
Exemple #28
0
        // ---- SECTION: public methods --------------*
        //
        // GetAdjustmentRules -
        //
        // returns a cloned array of AdjustmentRule objects
        //
        public AdjustmentRule[] GetAdjustmentRules()
        {
            if (_adjustmentRules == null)
            {
                return Array.Empty<AdjustmentRule>();
            }

            // The rules we use in Unix cares mostly about the start and end dates but doesn’t fill the transition start and end info. 
            // as the rules now is public, we should fill it properly so the caller doesn’t have to know how we use it internally 
            // and can use it as it is used in Windows

            AdjustmentRule[] rules = new AdjustmentRule[_adjustmentRules.Length];

            for (int i = 0; i < _adjustmentRules.Length; i++)
            {
                var rule = _adjustmentRules[i];
                var start = rule.DateStart.Kind == DateTimeKind.Utc ?
                            new DateTime(TimeZoneInfo.ConvertTime(rule.DateStart, this).Ticks, DateTimeKind.Unspecified) :
                            rule.DateStart;
                var end = rule.DateEnd.Kind == DateTimeKind.Utc ?
                            new DateTime(TimeZoneInfo.ConvertTime(rule.DateEnd, this).Ticks - 1, DateTimeKind.Unspecified) :
                            rule.DateEnd;

                var startTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, start.Hour, start.Minute, start.Second), start.Month, start.Day);
                var endTransition = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, end.Hour, end.Minute, end.Second), end.Month, end.Day);

                rules[i] = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(start.Date, end.Date, rule.DaylightDelta, startTransition, endTransition);
            }

            return rules;
        }
Exemple #29
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 #30
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()));
        }
 public static DateTime DaylightEnd(this AdjustmentRule adjustmentRule)
 {
     return(adjustmentRule.DaylightTransitionEnd.ToDateTime(adjustmentRule.DateEnd.Year).AddSeconds(-1));
 }
		private static void Validate (string id, TimeSpan baseUtcOffset, AdjustmentRule [] adjustmentRules)
		{
			if (id == null)
				throw new ArgumentNullException ("id");

			if (id == String.Empty)
				throw new ArgumentException ("id parameter is an empty string");

			if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0)
				throw new ArgumentException ("baseUtcOffset parameter does not represent a whole number of minutes");

			if (baseUtcOffset > new TimeSpan (14, 0, 0) || baseUtcOffset < new TimeSpan (-14, 0, 0))
				throw new ArgumentOutOfRangeException ("baseUtcOffset parameter is greater than 14 hours or less than -14 hours");

#if STRICT
			if (id.Length > 32)
				throw new ArgumentException ("id parameter shouldn't be longer than 32 characters");
#endif

			if (adjustmentRules != null && adjustmentRules.Length != 0) {
				AdjustmentRule prev = null;
				foreach (AdjustmentRule current in adjustmentRules) {
					if (current == null)
						throw new InvalidTimeZoneException ("one or more elements in adjustmentRules are null");

					if ((baseUtcOffset + current.DaylightDelta < new TimeSpan (-14, 0, 0)) ||
							(baseUtcOffset + current.DaylightDelta > new TimeSpan (14, 0, 0)))
						throw new InvalidTimeZoneException ("Sum of baseUtcOffset and DaylightDelta of one or more object in adjustmentRules array is greater than 14 or less than -14 hours;");

					if (prev != null && prev.DateStart > current.DateStart)
						throw new InvalidTimeZoneException ("adjustment rules specified in adjustmentRules parameter are not in chronological order");
					
					if (prev != null && prev.DateEnd > current.DateStart)
						throw new InvalidTimeZoneException ("some adjustment rules in the adjustmentRules parameter overlap");

					if (prev != null && prev.DateEnd == current.DateStart)
						throw new InvalidTimeZoneException ("a date can have multiple adjustment rules applied to it");

					prev = current;
				}
			}
		}
Exemple #33
0
        private TimeZoneInfo(string id, TimeSpan baseUtcOffset, string displayName, string standardDisplayName, string daylightDisplayName, TimeZoneInfo.AdjustmentRule [] adjustmentRules, bool disableDaylightSavingTime)
        {
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }

            if (id == String.Empty)
            {
                throw new ArgumentException("id parameter is an empty string");
            }

            if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0)
            {
                throw new ArgumentException("baseUtcOffset parameter does not represent a whole number of minutes");
            }

            if (baseUtcOffset > new TimeSpan(14, 0, 0) || baseUtcOffset < new TimeSpan(-14, 0, 0))
            {
                throw new ArgumentOutOfRangeException("baseUtcOffset parameter is greater than 14 hours or less than -14 hours");
            }

#if STRICT
            if (id.Length > 32)
            {
                throw new ArgumentException("id parameter shouldn't be longer than 32 characters");
            }
#endif

            bool supportsDaylightSavingTime = !disableDaylightSavingTime;

            if (adjustmentRules != null && adjustmentRules.Length != 0)
            {
                AdjustmentRule prev = null;
                foreach (AdjustmentRule current in adjustmentRules)
                {
                    if (current == null)
                    {
                        throw new InvalidTimeZoneException("one or more elements in adjustmentRules are null");
                    }

                    if ((baseUtcOffset + current.DaylightDelta < new TimeSpan(-14, 0, 0)) ||
                        (baseUtcOffset + current.DaylightDelta > new TimeSpan(14, 0, 0)))
                    {
                        throw new InvalidTimeZoneException("Sum of baseUtcOffset and DaylightDelta of one or more object in adjustmentRules array is greater than 14 or less than -14 hours;");
                    }

                    if (prev != null && prev.DateStart > current.DateStart)
                    {
                        throw new InvalidTimeZoneException("adjustment rules specified in adjustmentRules parameter are not in chronological order");
                    }

                    if (prev != null && prev.DateEnd > current.DateStart)
                    {
                        throw new InvalidTimeZoneException("some adjustment rules in the adjustmentRules parameter overlap");
                    }

                    if (prev != null && prev.DateEnd == current.DateStart)
                    {
                        throw new InvalidTimeZoneException("a date can have multiple adjustment rules applied to it");
                    }

                    prev = current;
                }
            }
            else
            {
                supportsDaylightSavingTime = false;
            }

            this.id                         = id;
            this.baseUtcOffset              = baseUtcOffset;
            this.displayName                = displayName ?? id;
            this.standardDisplayName        = standardDisplayName ?? id;
            this.daylightDisplayName        = daylightDisplayName;
            this.supportsDaylightSavingTime = supportsDaylightSavingTime;
            this.adjustmentRules            = adjustmentRules;
        }
            /// <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);
            }
		private bool IsInDST (AdjustmentRule rule, DateTime dateTime)
		{
			// Check whether we're in the dateTime year's DST period
			if (IsInDSTForYear (rule, dateTime, dateTime.Year))
				return true;

			// We might be in the dateTime previous year's DST period
			return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
		}
Exemple #36
0
        private static void TZif_GenerateAdjustmentRules(out AdjustmentRule[] rules, DateTime[] dts, Byte[] typeOfLocalTime,
                                                         TZifType[] transitionType, Boolean[] StandardTime, Boolean[] GmtTime)
        {
            rules = null;

            int index = 0;
            List<AdjustmentRule> rulesList = new List<AdjustmentRule>(1);
            bool succeeded = true;

            while (succeeded && index < dts.Length)
            {
                succeeded = TZif_GenerateAdjustmentRule(ref index, ref rulesList, dts, typeOfLocalTime, transitionType, StandardTime, GmtTime);
            }

            rules = rulesList.ToArray();
            if (rules != null && rules.Length == 0)
            {
                rules = null;
            }
        }
Exemple #37
0
 public OffsetAndRule(int year, TimeSpan offset, AdjustmentRule rule)
 {
     Year   = year;
     Offset = offset;
     Rule   = rule;
 }
        internal TimeZoneInfo(
                String id,
                TimeSpan baseUtcOffset,
                String displayName,
                String standardDisplayName,
                String daylightDisplayName,
                AdjustmentRule[] adjustmentRules,
                Boolean disableDaylightSavingTime)
        {
            Boolean adjustmentRulesSupportDst;
            ValidateTimeZoneInfo(id, baseUtcOffset, adjustmentRules, out adjustmentRulesSupportDst);

            if (!disableDaylightSavingTime && adjustmentRules != null && adjustmentRules.Length > 0)
            {
                _adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone();
            }

            _id = id;
            _baseUtcOffset = baseUtcOffset;
            _displayName = displayName;
            _standardDisplayName = standardDisplayName;
            _daylightDisplayName = (disableDaylightSavingTime ? null : daylightDisplayName);
            _supportsDaylightSavingTime = adjustmentRulesSupportDst && !disableDaylightSavingTime;
        }