public TimeSpan GetUtcOffset(DateTime dateTime) { if (IsDaylightSavingTime(dateTime)) { AdjustmentRule rule = GetApplicableRule(dateTime); if (rule != null) { return(BaseUtcOffset + rule.DaylightDelta); } } return(BaseUtcOffset); }
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); }
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); }
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 }); }
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); }
/// <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); } }
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); } }
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); }
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); } }
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); }
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 } }; }
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)); } }
/// <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(); }
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)); }
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); }
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); }
// -------- 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()); }
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); }
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())); } }
// // 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; }
/// <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); }
// ---- 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; }
private static bool TZif_GenerateAdjustmentRule(ref int startIndex, ref List <AdjustmentRule> rulesList, DateTime[] dts, Byte[] typeOfLocalTime, TZifType[] transitionType, Boolean[] StandardTime, Boolean[] GmtTime) { int index = startIndex; bool Dst = false; int DstStartIndex = -1; int DstEndIndex = -1; DateTime startDate = DateTime.MinValue.Date; DateTime endDate = DateTime.MaxValue.Date; // find the next DST transition start time index while (!Dst && index < typeOfLocalTime.Length) { int typeIndex = typeOfLocalTime[index]; if (typeIndex < transitionType.Length && transitionType[typeIndex].IsDst) { // found the next DST transition start time Dst = true; DstStartIndex = index; } else { index++; } } // find the next DST transition end time index while (Dst && index < typeOfLocalTime.Length) { int typeIndex = typeOfLocalTime[index]; if (typeIndex < transitionType.Length && !transitionType[typeIndex].IsDst) { // found the next DST transition end time Dst = false; DstEndIndex = index; } else { index++; } } // // construct the adjustment rule from the two indices // if (DstStartIndex >= 0) { DateTime startTransitionDate = dts[DstStartIndex]; DateTime endTransitionDate; if (DstEndIndex == -1) { // we found a DST start but no DST end; in this case use the // prior non-DST entry if it exists, else use the current entry for both start and end (e.g., zero daylightDelta) if (DstStartIndex > 0) { DstEndIndex = DstStartIndex - 1; } else { DstEndIndex = DstStartIndex; } endTransitionDate = DateTime.MaxValue; } else { endTransitionDate = dts[DstEndIndex]; } int dstStartTypeIndex = typeOfLocalTime[DstStartIndex]; int dstEndTypeIndex = typeOfLocalTime[DstEndIndex]; TimeSpan daylightBias = transitionType[dstStartTypeIndex].UtcOffset - transitionType[dstEndTypeIndex].UtcOffset; // TZif supports seconds-level granularity with offsets but TimeZoneInfo only supports minutes since it aligns // with DateTimeOffset, SQL Server, and the W3C XML Specification if (daylightBias.Ticks % TimeSpan.TicksPerMinute != 0) { daylightBias = new TimeSpan(daylightBias.Hours, daylightBias.Minutes, 0); } // // the normal case is less than 12 months between transition times. However places like America/Catamarca // have DST from 1946-1963 straight without a gap. In that case we need to create a series of Adjustment // Rules to fudge the multi-year DST period // if ((endTransitionDate - startTransitionDate).Ticks <= TimeSpan.TicksPerDay * 364) { TransitionTime dstStart; TransitionTime dstEnd; TimeSpan startTransitionOffset = (DstStartIndex > 0 ? transitionType[typeOfLocalTime[DstStartIndex - 1]].UtcOffset : transitionType[dstEndTypeIndex].UtcOffset); TimeSpan endTransitionOffset = (DstEndIndex > 0 ? transitionType[typeOfLocalTime[DstEndIndex - 1]].UtcOffset : transitionType[dstStartTypeIndex].UtcOffset); dstStart = TZif_CalculateTransitionTime(startTransitionDate, startTransitionOffset, transitionType[dstStartTypeIndex], StandardTime[dstStartTypeIndex], GmtTime[dstStartTypeIndex], out startDate); dstEnd = TZif_CalculateTransitionTime(endTransitionDate, endTransitionOffset, transitionType[dstEndTypeIndex], StandardTime[dstEndTypeIndex], GmtTime[dstEndTypeIndex], out endDate); // calculate the AdjustmentRule end date if (DstStartIndex >= DstEndIndex) { // we found a DST start but no DST end endDate = DateTime.MaxValue.Date; } AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(startDate, endDate, daylightBias, dstStart, dstEnd); rulesList.Add(r); } else { // create the multi-year DST rule series: // // For example America/Catamarca: // 1946-10-01T04:00:00.0000000Z {-03:00:00 DST=True} // 1963-10-01T03:00:00.0000000Z {-04:00:00 DST=False} // // gets converted into a series of overlapping 5/7month adjustment rules: // // [AdjustmentRule #0] // start rule // [1946/09/31 - 1947/06/15] // * starts 1 day prior to startTransitionDate // [start: 10/01 @4:00 ] // * N months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _end_ is outside the range // // [AdjustmentRule #1] // middle-year all-DST rule // [1947/06/16 - 1947/11/15] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * 5 months long, stopping at month 6 or 11 // [end : 12/15 ] // notice how the _start and end_ are outside the range // // [AdjustmentRule #2] // middle-year all-DST rule // [1947/11/16 - 1947/06/15] // * starts 1 day after last day in previous rule // [start: 10/01 ] // * 7 months long, stopping at month 6 or 11 // [end : 07/15 ] // notice how the _start and end_ are outside the range // // ......................... // // [AdjustmentRule #N] // end rule // [1963/06/16 - 1946/10/02] // * starts 1 day after last day in previous rule // [start: 05/15 ] // * N months long, stopping 1 day after endTransitionDate // [end : 10/01 ] // notice how the _start_ is outside the range // // create the first rule from N to either 06/15 or 11/15 TZif_CreateFirstMultiYearRule(ref rulesList, daylightBias, startTransitionDate, DstStartIndex, dstStartTypeIndex, dstEndTypeIndex, dts, transitionType, typeOfLocalTime, StandardTime, GmtTime); // create the filler rules TZif_CreateMiddleMultiYearRules(ref rulesList, daylightBias, endTransitionDate); // create the last rule TZif_CreateLastMultiYearRule(ref rulesList, daylightBias, endTransitionDate, DstStartIndex, dstStartTypeIndex, DstEndIndex, dstEndTypeIndex, dts, transitionType, typeOfLocalTime, StandardTime, GmtTime); } startIndex = index + 1; return(true); } // setup the start values for the next call to TZif_GenerateAdjustmentRule(...) startIndex = index + 1; return(false); // did not create a new AdjustmentRule }
private static 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; } } }
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); }
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; } }
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; }