public static void FixTimeZoneDSTRRules (TimeZoneInfo tz, ITimeZone iCalTz) { var adjustments = tz.GetAdjustmentRules(); foreach (var tziItems in iCalTz.TimeZoneInfos) { var matchingAdj = adjustments.FirstOrDefault(a => (a.DateStart.Year == tziItems.Start.Year)) ?? adjustments.FirstOrDefault(); if (matchingAdj != null) { if ((matchingAdj.DateEnd.Year != 9999) && !(tziItems.Name.Equals("STANDARD") && matchingAdj == adjustments.Last())) { tziItems.RecurrenceRules[0].Until = DateTime.SpecifyKind(matchingAdj.DateEnd.Date.AddDays(1).Subtract(tz.BaseUtcOffset), DateTimeKind.Utc); } if (tziItems.Name.Equals("STANDARD")) { if (!matchingAdj.DaylightTransitionEnd.IsFixedDateRule) { var startYear = tziItems.Start.Year; tziItems.Start = CalcTransitionStart(matchingAdj.DaylightTransitionEnd, startYear); } } else { if (!matchingAdj.DaylightTransitionStart.IsFixedDateRule) { var startYear = tziItems.Start.Year; tziItems.Start = CalcTransitionStart(matchingAdj.DaylightTransitionStart, startYear); } } } } }
static DateTimeConverter() { LocalZoneInfo = TimeZoneInfo.Local; CurrentZone = TimeZone.CurrentTimeZone; var offset = LocalZoneInfo.BaseUtcOffset; var sbWithout = new StringBuilder(); if (offset.TotalSeconds >= 0) sbWithout.Append('+'); sbWithout.Append(offset.Hours.ToString("00")); sbWithout.Append(':'); sbWithout.Append(offset.Minutes.ToString("00")); //tough luck if you have seconds in timezone offset TimeZoneWithoutDaylightSaving = sbWithout.ToString(); var rules = LocalZoneInfo.GetAdjustmentRules(); if (rules.Length == 1 && rules[0].DateStart == DateTime.MinValue && rules[0].DateEnd == DateTime.MinValue) { var sbWith = new StringBuilder(); var totalOffset = offset.Add(rules[0].DaylightDelta); if (totalOffset.TotalSeconds >= 0) sbWith.Append('+'); sbWith.Append(totalOffset.Hours.ToString("00")); sbWith.Append(':'); sbWith.Append(totalOffset.Minutes.ToString("00")); TimeZoneWithDaylightSaving = sbWith.ToString(); } }
public static void FixTimeZoneDSTRRules (TimeZoneInfo tz, DDay.iCal.iCalTimeZone iCalTz) { var adjustments = tz.GetAdjustmentRules(); foreach (var tziItems in iCalTz.TimeZoneInfos) { var matchingAdj = adjustments.FirstOrDefault (a => (a.DateStart.Year == tziItems.Start.Year)) ?? adjustments.FirstOrDefault(); if (matchingAdj != null && matchingAdj.DateEnd.Year != 9999) { if (!(tziItems.Name.Equals ("STANDARD") && matchingAdj == adjustments.Last())) { tziItems.RecurrenceRules[0].Until = DateTime.SpecifyKind (matchingAdj.DateEnd.Date.AddDays (1).Subtract (tz.BaseUtcOffset), DateTimeKind.Utc); } } } }
/// <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. TimeZoneInfo.AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRules(); 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). TimeZoneInfo.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 iCalTimeZone FromSystemTimeZone(System.TimeZoneInfo tzinfo) { var adjustmentRules = tzinfo.GetAdjustmentRules(); var utcOffset = tzinfo.BaseUtcOffset; var dday_tz = new iCalTimeZone(); foreach (var adjustmentRule in adjustmentRules) { var delta = adjustmentRule.DaylightDelta; dday_tz.TZID = tzinfo.Id; var dday_tzinfo_standard = new DDay.iCal.Components.iCalTimeZoneInfo(); dday_tzinfo_standard.Name = "STANDARD"; dday_tzinfo_standard.Start = adjustmentRule.DateStart; if (dday_tzinfo_standard.Start.Year < 1800) { dday_tzinfo_standard.Start = dday_tzinfo_standard.Start.AddYears(1800 - dday_tzinfo_standard.Start.Year); } dday_tzinfo_standard.TZOffsetFrom = new DDay.iCal.DataTypes.UTC_Offset(utcOffset + delta); dday_tzinfo_standard.TZOffsetTo = new DDay.iCal.DataTypes.UTC_Offset(utcOffset); PopulateiCalTimeZoneInfo(dday_tzinfo_standard, adjustmentRule.DaylightTransitionEnd, adjustmentRule.DateStart.Year); // Add the "standard" time rule to the time zone dday_tz.AddChild(dday_tzinfo_standard); var dday_tzinfo_daylight = new DDay.iCal.Components.iCalTimeZoneInfo(); dday_tzinfo_daylight.Name = "DAYLIGHT"; dday_tzinfo_daylight.Start = adjustmentRule.DateStart; if (dday_tzinfo_daylight.Start.Year < 1800) { dday_tzinfo_daylight.Start = dday_tzinfo_daylight.Start.AddYears(1800 - dday_tzinfo_daylight.Start.Year); } dday_tzinfo_daylight.TZOffsetFrom = new DDay.iCal.DataTypes.UTC_Offset(utcOffset); dday_tzinfo_daylight.TZOffsetTo = new DDay.iCal.DataTypes.UTC_Offset(utcOffset + delta); PopulateiCalTimeZoneInfo(dday_tzinfo_daylight, adjustmentRule.DaylightTransitionStart, adjustmentRule.DateStart.Year); // Add the "daylight" time rule to the time zone dday_tz.AddChild(dday_tzinfo_daylight); } return(dday_tz); }
private static PhpArray GetTimeOfDay(DateTime utc, TimeZoneInfo/*!*/ zone) { PhpArray result = new PhpArray(0, 4); DateTime local = TimeZoneInfo.ConvertTimeFromUtc(utc, zone); int current_dst = 0; if (zone.IsDaylightSavingTime(local)) { var rules = zone.GetAdjustmentRules(); for (int i = 0; i < rules.Length; i++) { if (rules[i].DateStart <= local && rules[i].DateEnd >= local) { current_dst = (int)rules[i].DaylightDelta.TotalHours; break; } } } const int ticks_per_microsecond = (int)TimeSpan.TicksPerMillisecond / 1000; result["sec"] = DateTimeUtils.UtcToUnixTimeStamp(utc); result["usec"] = (int)(local.Ticks % TimeSpan.TicksPerSecond) / ticks_per_microsecond; result["minuteswest"] = (int)(utc - local).TotalMinutes; result["dsttime"] = current_dst; return result;
public static iCalTimeZone FromSystemTimeZone(System.TimeZoneInfo tzinfo, DateTime earlistDateTimeToSupport, bool includeHistoricalData) { var adjustmentRules = tzinfo.GetAdjustmentRules(); var utcOffset = tzinfo.BaseUtcOffset; var dday_tz = new iCalTimeZone(); dday_tz.TZID = tzinfo.Id; IDateTime earliest = new iCalDateTime(earlistDateTimeToSupport); foreach (var adjustmentRule in adjustmentRules) { // Only include historical data if asked to do so. Otherwise, // use only the most recent adjustment rule available. if (!includeHistoricalData && adjustmentRule.DateEnd < earlistDateTimeToSupport) { continue; } var delta = adjustmentRule.DaylightDelta; var dday_tzinfo_standard = new DDay.iCal.iCalTimeZoneInfo(); dday_tzinfo_standard.Name = "STANDARD"; dday_tzinfo_standard.TimeZoneName = tzinfo.StandardName; dday_tzinfo_standard.Start = new iCalDateTime(new DateTime(adjustmentRule.DateStart.Year, adjustmentRule.DaylightTransitionEnd.Month, adjustmentRule.DaylightTransitionEnd.Day, adjustmentRule.DaylightTransitionEnd.TimeOfDay.Hour, adjustmentRule.DaylightTransitionEnd.TimeOfDay.Minute, adjustmentRule.DaylightTransitionEnd.TimeOfDay.Second).AddDays(1)); if (dday_tzinfo_standard.Start.LessThan(earliest)) { dday_tzinfo_standard.Start = dday_tzinfo_standard.Start.AddYears(earliest.Year - dday_tzinfo_standard.Start.Year); } dday_tzinfo_standard.OffsetFrom = new UTCOffset(utcOffset + delta); dday_tzinfo_standard.OffsetTo = new UTCOffset(utcOffset); PopulateiCalTimeZoneInfo(dday_tzinfo_standard, adjustmentRule.DaylightTransitionEnd, adjustmentRule.DateStart.Year); // Add the "standard" time rule to the time zone dday_tz.AddChild(dday_tzinfo_standard); if (tzinfo.SupportsDaylightSavingTime) { var dday_tzinfo_daylight = new DDay.iCal.iCalTimeZoneInfo(); dday_tzinfo_daylight.Name = "DAYLIGHT"; dday_tzinfo_daylight.TimeZoneName = tzinfo.DaylightName; dday_tzinfo_daylight.Start = new iCalDateTime(new DateTime(adjustmentRule.DateStart.Year, adjustmentRule.DaylightTransitionStart.Month, adjustmentRule.DaylightTransitionStart.Day, adjustmentRule.DaylightTransitionStart.TimeOfDay.Hour, adjustmentRule.DaylightTransitionStart.TimeOfDay.Minute, adjustmentRule.DaylightTransitionStart.TimeOfDay.Second)); if (dday_tzinfo_daylight.Start.LessThan(earliest)) { dday_tzinfo_daylight.Start = dday_tzinfo_daylight.Start.AddYears(earliest.Year - dday_tzinfo_daylight.Start.Year); } dday_tzinfo_daylight.OffsetFrom = new UTCOffset(utcOffset); dday_tzinfo_daylight.OffsetTo = new UTCOffset(utcOffset + delta); PopulateiCalTimeZoneInfo(dday_tzinfo_daylight, adjustmentRule.DaylightTransitionStart, adjustmentRule.DateStart.Year); // Add the "daylight" time rule to the time zone dday_tz.AddChild(dday_tzinfo_daylight); } } // If no time zone information was recorded, at least // add a STANDARD time zone element to indicate the // base time zone information. if (dday_tz.TimeZoneInfos.Count == 0) { var dday_tzinfo_standard = new DDay.iCal.iCalTimeZoneInfo(); dday_tzinfo_standard.Name = "STANDARD"; dday_tzinfo_standard.TimeZoneName = tzinfo.StandardName; dday_tzinfo_standard.Start = earliest; dday_tzinfo_standard.OffsetFrom = new UTCOffset(utcOffset); dday_tzinfo_standard.OffsetTo = new UTCOffset(utcOffset); // Add the "standard" time rule to the time zone dday_tz.AddChild(dday_tzinfo_standard); } return(dday_tz); }
/// <summary> /// Initializes a new instance of the <see cref="TimeZoneDefinition"/> class. /// </summary> /// <param name="timeZoneInfo">The time zone info used to initialize this definition.</param> internal TimeZoneDefinition(TimeZoneInfo timeZoneInfo) : this() { this.Id = timeZoneInfo.Id; this.Name = timeZoneInfo.DisplayName; // TimeZoneInfo only supports one standard period, which bias is the time zone's base // offset to UTC. TimeZonePeriod standardPeriod = new TimeZonePeriod(); standardPeriod.Id = TimeZonePeriod.StandardPeriodId; standardPeriod.Name = TimeZonePeriod.StandardPeriodName; standardPeriod.Bias = -timeZoneInfo.BaseUtcOffset; TimeZoneInfo.AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRules(); TimeZoneTransition transitionToStandardPeriod = new TimeZoneTransition(this, standardPeriod); if (adjustmentRules.Length == 0) { this.periods.Add(standardPeriod.Id, standardPeriod); // 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. TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, "0"); transitionGroup.Transitions.Add(transitionToStandardPeriod); this.transitionGroups.Add(transitionGroup.Id, transitionGroup); TimeZoneTransition initialTransition = new TimeZoneTransition(this, transitionGroup); this.transitions.Add(initialTransition); } else { for (int i = 0; i < adjustmentRules.Length; i++) { TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, this.transitionGroups.Count.ToString()); transitionGroup.InitializeFromAdjustmentRule(adjustmentRules[i], standardPeriod); this.transitionGroups.Add(transitionGroup.Id, transitionGroup); TimeZoneTransition transition; if (i == 0) { // If the first adjustment rule's start date in not undefined (DateTime.MinValue) // we need to add a dummy group with a single, simple transition to the Standard // period and a group containing the transitions mapping to the adjustment rule. if (adjustmentRules[i].DateStart > DateTime.MinValue.Date) { TimeZoneTransition transitionToDummyGroup = new TimeZoneTransition( this, this.CreateTransitionGroupToPeriod(standardPeriod)); this.transitions.Add(transitionToDummyGroup); AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup); absoluteDateTransition.DateTime = adjustmentRules[i].DateStart; transition = absoluteDateTransition; this.periods.Add(standardPeriod.Id, standardPeriod); } else { transition = new TimeZoneTransition(this, transitionGroup); } } else { AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup); absoluteDateTransition.DateTime = adjustmentRules[i].DateStart; transition = absoluteDateTransition; } this.transitions.Add(transition); } // If the last adjustment rule's end date is not undefined (DateTime.MaxValue), // we need to create another absolute date transition that occurs the date after // the last rule's end date. We target this additional transition to a group that // contains a single simple transition to the Standard period. DateTime lastAdjustmentRuleEndDate = adjustmentRules[adjustmentRules.Length - 1].DateEnd; if (lastAdjustmentRuleEndDate < DateTime.MaxValue.Date) { AbsoluteDateTransition transitionToDummyGroup = new AbsoluteDateTransition( this, this.CreateTransitionGroupToPeriod(standardPeriod)); transitionToDummyGroup.DateTime = lastAdjustmentRuleEndDate.AddDays(1); this.transitions.Add(transitionToDummyGroup); } } }
/// <summary> /// Converts a DateTime to Utc, considering DST jumps when starting or ending. /// </summary> /// <param name="dateTime"></param> /// <param name="timeZoneInfo"></param> /// <returns></returns> public static DateTime ConvertToUtcDateTime(DateTime dateTime, TimeZoneInfo timeZoneInfo) { if (timeZoneInfo.IsInvalidTime(dateTime)) { // Determinando o intervalo inexistente, por conta do // adiantamento de horário de verão, // que contém a data e hora passada em practiceDateTime. // e.g. horário é adiantado no dia 2012/10/21 às 00:00 em 1 hora, // então todos os horários no intervalo seguinte são inválidos: // [2012/10/21 00:00:00,0000000 ~ 2012/10/21 01:00:00,0000000[ // O intervalo retornado é exclusivo em ambas as pontas, // de forma que as data em ambas as pontas sejam VÁLIDAS. // Então o intervalo de exemplo acima será dado assim: // ]2012/10/20 23:59:59,9999999 ~ 2012/10/21 01:00:00,0000000[ var invalidIntervals = timeZoneInfo.GetAdjustmentRules() .Where(ar => ar.DaylightDelta != TimeSpan.Zero) .Select(ar => ar.DaylightDelta > TimeSpan.Zero ? new { Delta = ar.DaylightDelta, Transition = ar.DaylightTransitionStart, Date = ar.DateStart } : new { Delta = -ar.DaylightDelta, Transition = ar.DaylightTransitionEnd, Date = ar.DateStart }) .Select(x => new { Start = GetTransitionDateTime(x.Transition, x.Date.Year), x.Delta }) .Select(x => new { x.Start, x.Delta, End = (x.Start + x.Delta).AddTicks(-1) }) .Select(x => new { StartExclusive = x.Start.AddTicks(-1), EndExclusive = x.End.AddTicks(1) }) .Where(x => x.StartExclusive < dateTime && x.EndExclusive > dateTime) .ToList(); // Deve haver apenas um intervalo. var invalidInterval = invalidIntervals.Single(); // Determinando a ponta do intervalo que está dentro do dia atual, passado em practiceDateTime. var dateTime2 = dateTime.Day == invalidInterval.StartExclusive.Day ? invalidInterval.StartExclusive : invalidInterval.EndExclusive; // Convertendo a data para UTC. var result = TimeZoneInfo.ConvertTimeToUtc(dateTime2, timeZoneInfo); return result; } else { var result = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZoneInfo); return result; } }
static TimeZoneInfo.AdjustmentRule GetSystemTimeZoneRule(DateTime now, TimeZoneInfo tzi) { if (!tzi.SupportsDaylightSavingTime) { return null; } var rules = tzi.GetAdjustmentRules(); if (rules == null) { return null; } foreach (var rule in rules) { if ((rule.DateStart <= now) && (rule.DateEnd >= now)) { return rule; } } return null; }
/// <summary> /// Creates a <see cref="VTimeZone"/> from a <see cref="TimeZoneInfo"/> object. /// </summary> /// <param name="tzi"> /// The <see cref="TimeZoneInfo"/> to convert. /// </param> /// <returns> /// A <see cref="VTimeZone"/> representing the <paramref name="tzi"/>. /// </returns> /// <example> /// The following snippet demonstrates how to create an instance of the <see cref="VTimeZone"/> class for the /// local time zone. /// <code> /// var localTimeZone = VTimeZone.FromTimeZoneInfo(TimeZoneInfo.Local); /// </code> /// </example> /// <seealso cref="VCalendar.ForLocalTimeZone"/> public static VTimeZone FromTimeZoneInfo(TimeZoneInfo tzi) { Guard.IsNotNull(tzi, "tzi"); var tz = new VTimeZone { Id = tzi.DisplayName }; // Simple case of no adjustments. if (!tzi.SupportsDaylightSavingTime) { tz.Adjustments.Add(new StandardChange { StartsOn = new DateTime(0, DateTimeKind.Local), Name = new Text(CultureInfo.CurrentCulture.Name, tzi.StandardName), OffsetFrom = tzi.BaseUtcOffset, OffsetTo = tzi.BaseUtcOffset }); return tz; } // Convert TZI adjustments. Each adjustment is DaylightChange. // TODO: Need to synthesize the StandardChange. // TODO: Rewrite when RecurrenceRule is functional. foreach (var adjustment in tzi.GetAdjustmentRules()) { var daylight = new DaylightChange { Name = new Text(CultureInfo.CurrentCulture.Name, tzi.DaylightName), StartsOn = adjustment.DateStart + adjustment.DaylightTransitionStart.TimeOfDay.TimeOfDay, OffsetFrom = tzi.BaseUtcOffset, OffsetTo = tzi.BaseUtcOffset + adjustment.DaylightDelta, }; if (adjustment.DaylightTransitionStart.IsFixedDateRule) { throw new NotImplementedException("TimeZoneInfo with fixed date rule."); } else { var s = new StringBuilder("FREQ=YEARLY;WKST=MO"); s.AppendFormat(";BYMONTH={0}", adjustment.DaylightTransitionStart.Month); s.AppendFormat(";Day={0}{1}", adjustment.DaylightTransitionStart.Week == 5 ? -1 : adjustment.DaylightTransitionStart.Week, adjustment.DaylightTransitionStart.DayOfWeek.ToRfc5545WeekDayName()); daylight.RecurrenceRule = RecurrenceRule.Parse(s.ToString()); } tz.Adjustments.Add(daylight); } return tz; }