public static DateTimeOffset ToDateTimeOffset(this DateTime dt, TimeZoneInfo tz)
        {
            if (dt.Kind != DateTimeKind.Unspecified)
            {
                // Handle UTC or Local kinds (regular and hidden 4th kind)
                DateTimeOffset dto = new DateTimeOffset(dt.ToUniversalTime(), TimeSpan.Zero);
                return(TimeZoneInfo.ConvertTime(dto, tz));
            }

            if (tz.IsAmbiguousTime(dt))
            {
                // Prefer the daylight offset, because it comes first sequentially (1:30 ET becomes
                // 1:30 EDT)
                TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
                TimeSpan   offset  = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
                return(new DateTimeOffset(dt, offset));
            }

            if (tz.IsInvalidTime(dt))
            {
                // Advance by the gap, and return with the daylight offset (2:30 ET becomes 3:30 EDT)
                TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
                TimeSpan   gap     = offsets[1] - offsets[0];
                return(new DateTimeOffset(dt.Add(gap), offsets[1]));
            }

            // Simple case
            return(new DateTimeOffset(dt, tz.GetUtcOffset(dt)));
        }
Beispiel #2
0
        /// <summary>
        /// Gets <see cref="DateTimeOffset"/> list for specified <see cref="DateTimeOffset"/> in the specified <see cref="TimeZoneInfo"/>.
        /// If the result contains two DateTimeOffsets, the index-1 contains standard time.
        /// </summary>
        /// <param name="dateTime"><see cref="DateTime"/> to calculate <see cref="DateTimeOffset"/>.
        ///   <see cref="DateTimeKind"/> is important because there are ambiguous datetimes in some timezones(that has daylight saving time).
        ///   For <see cref="DateTimeKind.Utc"/>, only one <see cref="DateTimeOffset"/> is in the returned list.
        ///   For <see cref="DateTimeKind.Unspecified"/> or <see cref="DateTimeKind.Local"/>, there is a case that two <see cref="DateTimeOffset"/> items are returned when the datetime is ambiguous.
        ///   For <see cref="DateTimeKind.Local"/>, there are more complicated situations that local time zone also have ambiguous datetimes.
        /// </param>
        /// <param name="timeZoneInfo"><see cref="TimeZoneInfo"/> to calculate <see cref="DateTimeOffset"/>.</param>
        /// <returns><see cref="DateTimeOffset"/>.</returns>
        /// <remarks>
        ///   <see cref="DateTimeKind"/> is important because there are ambiguous datetimes in some timezones(that has daylight saving time).
        ///   For <see cref="DateTimeKind.Utc"/>, only one <see cref="DateTimeOffset"/> is in the returned list.
        ///   For <see cref="DateTimeKind.Unspecified"/> or <see cref="DateTimeKind.Local"/>, there is a case that two <see cref="DateTimeOffset"/> items are returned when the datetime is ambiguous.
        ///   For <see cref="DateTimeKind.Local"/>, there are more complicated situations that local time zone also have ambiguous datetimes.
        /// </remarks>
        /// <exception cref="ArgumentException">The dateTime parameter represents an invalid time.</exception>
        /// <exception cref="ArgumentNullException">The timeZoneInfo parameter is null.</exception>
        public static DateTimeOffset[] GetDateTimeOffsets(DateTime dateTime, TimeZoneInfo timeZoneInfo)
        {
            if (timeZoneInfo == null)
            {
                throw new ArgumentNullException("timeZoneInfo");
            }

            if (dateTime.Kind == DateTimeKind.Utc || !(timeZoneInfo.SupportsDaylightSavingTime))
            {
                return(new DateTimeOffset[] { GetDateTimeOffset(dateTime, timeZoneInfo) });
            }

            DateTime dateTimeAdjusted = dateTime;

            if (dateTime.Kind == DateTimeKind.Local && !(TimeZoneInfo.Local.Equals(timeZoneInfo)))
            {
                dateTimeAdjusted = TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.Local, timeZoneInfo);
            }

            if (dateTimeAdjusted.Kind != DateTimeKind.Unspecified)
            {
                dateTimeAdjusted = DateTime.SpecifyKind(dateTimeAdjusted, DateTimeKind.Unspecified);
            }

            if (TimeZoneInfo.Utc.Equals(timeZoneInfo))
            {
                return(new DateTimeOffset[] { new DateTimeOffset(dateTimeAdjusted, TimeSpan.Zero) });
            }
            else if (timeZoneInfo.IsInvalidTime(dateTimeAdjusted))
            {
                throw new ArgumentException(ResourceMessage.ErrorMessages.InvalidDateTime, "dateTime");
            }
            else if (!(timeZoneInfo.IsAmbiguousTime(dateTimeAdjusted)))
            {
                return(new DateTimeOffset[] { new DateTimeOffset(dateTimeAdjusted, timeZoneInfo.GetUtcOffset(dateTimeAdjusted)) });
            }
            else
            {
                var timeSpans  = timeZoneInfo.GetAmbiguousTimeOffsets(dateTimeAdjusted);
                var results    = new List <DateTimeOffset>(2);
                var baseOffset = timeZoneInfo.BaseUtcOffset;

                foreach (var item in timeSpans)
                {
                    if (item == baseOffset)
                    {
                        results.Insert(0, new DateTimeOffset(dateTimeAdjusted, item));
                    }
                    else
                    {
                        results.Add(new DateTimeOffset(dateTimeAdjusted, item));
                    }
                }

                return(results.ToArray());
            }
        }
        // <Snippet1>
        private void ShowPossibleUtcTimes(DateTime ambiguousTime, TimeZoneInfo timeZone)
        {
            // Determine if time is ambiguous in target time zone
            if (!timeZone.IsAmbiguousTime(ambiguousTime))
            {
                Console.WriteLine("{0} is not ambiguous in time zone {1}.",
                                  ambiguousTime,
                                  timeZone.DisplayName);
            }
            else
            {
                // Display time and its time zone (local, UTC, or indicated by timeZone argument)
                string originalTimeZoneName;
                if (ambiguousTime.Kind == DateTimeKind.Utc)
                {
                    originalTimeZoneName = "UTC";
                }
                else if (ambiguousTime.Kind == DateTimeKind.Local)
                {
                    originalTimeZoneName = "local time";
                }
                else
                {
                    originalTimeZoneName = timeZone.DisplayName;
                }

                Console.WriteLine("{0} {1} maps to the following possible times:",
                                  ambiguousTime, originalTimeZoneName);
                // Get ambiguous offsets
                TimeSpan[] offsets = timeZone.GetAmbiguousTimeOffsets(ambiguousTime);
                // Handle times not in time zone of timeZone argument
                // Local time where timeZone is not local zone
                if ((ambiguousTime.Kind == DateTimeKind.Local) && !timeZone.Equals(TimeZoneInfo.Local))
                {
                    ambiguousTime = TimeZoneInfo.ConvertTime(ambiguousTime, TimeZoneInfo.Local, timeZone);
                }
                // UTC time where timeZone is not UTC zone
                else if ((ambiguousTime.Kind == DateTimeKind.Utc) && !timeZone.Equals(TimeZoneInfo.Utc))
                {
                    ambiguousTime = TimeZoneInfo.ConvertTime(ambiguousTime, TimeZoneInfo.Utc, timeZone);
                }

                // Display each offset and its mapping to UTC
                foreach (TimeSpan offset in offsets)
                {
                    if (offset.Equals(timeZone.BaseUtcOffset))
                    {
                        Console.WriteLine("If {0} is {1}, {2} UTC", ambiguousTime, timeZone.StandardName, ambiguousTime - offset);
                    }
                    else
                    {
                        Console.WriteLine("If {0} is {1}, {2} UTC", ambiguousTime, timeZone.DaylightName, ambiguousTime - offset);
                    }
                }
            }
        }
Beispiel #4
0
            public void DateIsNotAmbiguous()
            {
                if (Environment.OSVersion.Platform != PlatformID.Unix)
                {
                    throw new ArgumentException();
                }
                TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById("Europe/Brussels");
                DateTime     date     = new DateTime(2007, 05, 11, 11, 40, 00);

                brussels.GetAmbiguousTimeOffsets(date);
            }
Beispiel #5
0
        public static TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfo timeZoneInfo)
        {
            // Unlike the default behavior of TimeZoneInfo.GetUtcOffset, it is prefered to choose
            // the DAYLIGHT time when the input is ambiguous, because the daylight instance is the
            // FIRST instance, and time moves in a forward direction.

            TimeSpan offset = timeZoneInfo.IsAmbiguousTime(dateTime)
                ? timeZoneInfo.GetAmbiguousTimeOffsets(dateTime).Max()
                : timeZoneInfo.GetUtcOffset(dateTime);

            return(offset);
        }
Beispiel #6
0
            public void AmbiguousOffsets()
            {
                if (Environment.OSVersion.Platform != PlatformID.Unix)
                {
                    return;
                }
                TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById("Europe/Brussels");
                DateTime     date     = new DateTime(2007, 10, 28, 2, 30, 00);

                Assert.IsTrue(brussels.IsAmbiguousTime(date));
                Assert.AreEqual(2, brussels.GetAmbiguousTimeOffsets(date).Length);
                Assert.AreEqual(new TimeSpan[] { new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0) }, brussels.GetAmbiguousTimeOffsets(date));
            }
Beispiel #7
0
        // the point before DST/Standard change
        public static DateTimeOffset GetCurrentPeriodEnd(this TimeZoneInfo timeZone, DateTime value)
        {
            var next = GetAdjustmentDate(timeZone, value);

            if (next == DateTime.MaxValue)
            {
                throw new InvalidOperationException("date is not ambigous");
            }

            var list   = timeZone.GetAmbiguousTimeOffsets(value);
            var offset = list[0] == timeZone.GetUtcOffset(next) ? list[1] : list[0];

            return(new DateTimeOffset(next, offset));
        }
Beispiel #8
0
        internal static DateTimeOffset ToDateTimeOffset(this DateTime dateTime, TimeZoneInfo timeZoneInfo)
        {
            TimeSpan offset;

            if (timeZoneInfo.IsAmbiguousTime(dateTime))
            {
                // Ambiguous times happen when during backward transitions, such as the end of daylight saving time.
                // Since we were just told this time is ambiguous, there will always be exactly two offsets in the following array:
                TimeSpan[] offsets = timeZoneInfo.GetAmbiguousTimeOffsets(dateTime);

                // A reasonable common practice is to pick the first occurrence, which is always the largest offset in the array.
                // Ex: 2019-11-03T01:30:00 in the Pacific time zone occurs twice.  First at 1:30 PDT (-07:00), then an hour later
                //     at 1:30 PST (-08:00).  We choose PDT (-07:00) because it comes first sequentially.
                offset = TimeSpan.FromMinutes(Math.Max(offsets[0].TotalMinutes, offsets[1].TotalMinutes));
            }
            else if (timeZoneInfo.IsInvalidTime(dateTime))
            {
                // Invalid times happen during the gap created by a forward transition, such as the start of daylight saving time.
                // While they are not values that actually occur in correct local time, they are sometimes encountered
                // in scenarios such as a scheduled daily task.  In such cases, a reasonable common practice is to advance
                // to a valid local time by the amount of the transition gap (usually 1 hour).
                // Ex: 2019-03-10T02:30:00 does not exist in Pacific time.
                //     The local time went from 01:59:59 PST (-08:00) directly to 03:00:00 PDT (-07:00).
                //     We will advance by 1 hour to 03:30:00 which is in PDT (-07:00).

                // The gap is usually 1 hour, but not always - so it must be calculated
                TimeSpan earlierOffset = timeZoneInfo.GetUtcOffset(dateTime.AddDays(-1));
                TimeSpan laterOffset   = timeZoneInfo.GetUtcOffset(dateTime.AddDays(1));
                TimeSpan gap           = laterOffset - earlierOffset;

                dateTime = dateTime.Add(gap);
                offset   = laterOffset;
            }
            else
            {
                dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
                offset   = timeZoneInfo.GetUtcOffset(dateTime);
            }

            return(new DateTimeOffset(dateTime, offset));
        }
        /// <summary>
        /// Given a recurrence rule, get the next valid draw open and close based on a time zone. In the situation of DST
        /// ending, find the minimum of the ambigious times which comes after the afterTime argument. In the situation of DST
        /// starting, simply skip an invalid time provided by the library
        /// </summary>
        /// <param name="afterTime">The UTC time after which you want the next recurrence match</param>
        /// <param name="timeZoneId">The time zone you are calculatinig for</param>
        /// <param name="recurrence">The recurrence pattern</param>
        /// <returns>The next occurence in UTC</returns>
        public static DateTimeOffset GetNextOccurence(DateTimeOffset afterTime, string timeZoneId, List <Recurrence> recurrenceList)
        {
            DateTimeOffset nextUtc;

            TimeZoneInfo authorityTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);

            DateTime afterTimeLocalized = TimeZoneInfo.ConvertTime(afterTime, authorityTimeZone).DateTime;

            DateTime nextLocal = recurrenceList.Min(e => e.NextInstance(afterTimeLocalized, true));

            if (authorityTimeZone.IsInvalidTime(nextLocal))
            {
                // Invalid times occur when Daylight Savings starts and the clocks are moved forward
                // I.E. The clock is 1:59:59AM ST and becomes 3:00:00AM DST, thereby eliminating the hour from 2AM to 3AM
                // Unfortunately our recurrance library will give us 2:00:00AM as a valid time
                // Thus we must add an hour

                nextLocal = nextLocal.AddHours(1);

                nextUtc = new DateTimeOffset(nextLocal, authorityTimeZone.GetUtcOffset(nextLocal));
            }

            else if (authorityTimeZone.IsAmbiguousTime(nextLocal))
            {
                // Ambigious times occur when Daylight Savings ends and the clocks are moved backward
                // I.E. The clock is 1:59:59AM DST and becomes 1:00:00AM ST, thereby repeating the hour from 1AM to 2AM
                // In this situation, the recurrence library will not repeat the hour

                var minOffset = (from Offset in authorityTimeZone.GetAmbiguousTimeOffsets(nextLocal)
                                 let DrawOpen = new DateTimeOffset(nextLocal, Offset)
                                                where DrawOpen > afterTime
                                                orderby DrawOpen
                                                select new
                {
                    DrawOpen,
                    Offset
                }).First();

                nextUtc = minOffset.DrawOpen;
            }

            else if (authorityTimeZone.IsAmbiguousTime(nextLocal.AddHours(-1)) && recurrenceList.Any(z => z.OccursOn(nextLocal.AddHours(-1), true)))
            {
                // In this situation, the recurrence library potentially skipped the 2nd ambigious instance
                // So apply the two UTC time offsets and see if any of them is greater than the afterTime argument
                // If so, the recurrence library skipped the 2nd ambigious instance, and potentiallyValidTime is valid.
                // If not, nextLocal is correct

                DateTime potentiallyValidTime = nextLocal.AddHours(-1);

                var minOffset = (from Offset in authorityTimeZone.GetAmbiguousTimeOffsets(potentiallyValidTime)
                                 let DrawOpen = new DateTimeOffset(potentiallyValidTime, Offset)
                                                where DrawOpen > afterTime
                                                orderby DrawOpen
                                                select new
                {
                    DrawOpen,
                    Offset
                }).FirstOrDefault();

                if (minOffset == null)
                {
                    nextUtc = new DateTimeOffset(nextLocal, authorityTimeZone.GetUtcOffset(nextLocal));
                }

                else
                {
                    nextUtc = minOffset.DrawOpen;
                }
            }

            else
            {
                nextUtc = new DateTimeOffset(nextLocal, authorityTimeZone.GetUtcOffset(nextLocal));
            }

            return(nextUtc);
        }
Beispiel #10
0
 private static TimeSpan[] GetAmbiguousOffsets(TimeZoneInfo zone, DateTime ambiguousTime)
 {
     return(zone.GetAmbiguousTimeOffsets(ambiguousTime.AddTicks(1)));
 }
Beispiel #11
0
        public static string GetPossibleUtcTimes(TimeZoneInfo timeZone, DateTime ambiguousTime)
        {
            StringBuilder oSB = new StringBuilder();

            oSB.AppendLine("        Possible UTC Times for timezone:");

            // Determine if time is ambiguous in target time zone
            if (!timeZone.IsAmbiguousTime(ambiguousTime))
            {
                oSB.AppendFormat("            {0} is not ambiguous in time zone {1}.",
                                 ambiguousTime,
                                 timeZone.DisplayName);
            }
            else
            {
                // Display time and its time zone (local, UTC, or indicated by timeZone argument)
                string originalTimeZoneName = string.Empty;;
                if (ambiguousTime.Kind == DateTimeKind.Utc)
                {
                    originalTimeZoneName = "UTC";
                }
                else if (ambiguousTime.Kind == DateTimeKind.Local)
                {
                    originalTimeZoneName = "local time";
                }
                else
                {
                    originalTimeZoneName = timeZone.DisplayName;
                }

                oSB.AppendFormat("            {0} {1} maps to the following possible times:",
                                 ambiguousTime,
                                 originalTimeZoneName);
                // Get ambiguous offsets
                TimeSpan[] offsets = timeZone.GetAmbiguousTimeOffsets(ambiguousTime);
                // Handle times not in time zone of timeZone argument
                // Local time where timeZone is not local zone
                if ((ambiguousTime.Kind == DateTimeKind.Local) && !timeZone.Equals(TimeZoneInfo.Local))
                {
                    ambiguousTime = TimeZoneInfo.ConvertTime(ambiguousTime, TimeZoneInfo.Local, timeZone);
                }
                // UTC time where timeZone is not UTC zone
                else if ((ambiguousTime.Kind == DateTimeKind.Utc) && !timeZone.Equals(TimeZoneInfo.Utc))
                {
                    ambiguousTime = TimeZoneInfo.ConvertTime(ambiguousTime, TimeZoneInfo.Utc, timeZone);
                }

                // Display each offset and its mapping to UTC
                foreach (TimeSpan offset in offsets)
                {
                    if (offset.Equals(timeZone.BaseUtcOffset))
                    {
                        oSB.AppendFormat("                If {0} is {1}, {2} UTC", ambiguousTime, timeZone.StandardName, ambiguousTime - offset);
                    }
                    else
                    {
                        oSB.AppendFormat("                If {0} is {1}, {2} UTC", ambiguousTime, timeZone.DaylightName, ambiguousTime - offset);
                    }
                }
            }

            return(oSB.ToString());
        }
Beispiel #12
0
        public static string GetValuesFromTimezoneStringAndDateTime(TimeZoneInfo oTimeZoneInfo, DateTime oDateTime)
        {
            string        s   = string.Empty;
            StringBuilder oSB = new StringBuilder();



            oSB.AppendLine("    Using this Date: " + oDateTime.ToString());
            oSB.AppendLine("    Using this TimeZone: " + oTimeZoneInfo.ToString());
            oSB.AppendLine("    Id: " + oTimeZoneInfo.Id);
            oSB.AppendLine("    DisplayName: " + oTimeZoneInfo.DisplayName);
            oSB.AppendLine("    StandardName: " + oTimeZoneInfo.StandardName);
            oSB.AppendLine("    DaylightName: " + oTimeZoneInfo.DaylightName);
            oSB.AppendLine("    BaseUtcOffset: " + oTimeZoneInfo.BaseUtcOffset.ToString());
            oSB.AppendLine("    SupportsDaylightSavingTime: " + oTimeZoneInfo.SupportsDaylightSavingTime.ToString());
            oSB.AppendLine("    BaseUtcOffset: " + oTimeZoneInfo.BaseUtcOffset.ToString());
            oSB.AppendLine("        Days: " + oTimeZoneInfo.BaseUtcOffset.Days.ToString());
            oSB.AppendLine("        Hours: " + oTimeZoneInfo.BaseUtcOffset.Hours.ToString());
            oSB.AppendLine("        Milliseconds: " + oTimeZoneInfo.BaseUtcOffset.Milliseconds.ToString());
            oSB.AppendLine("        Minutes: " + oTimeZoneInfo.BaseUtcOffset.Minutes.ToString());
            oSB.AppendLine("        Seconds: " + oTimeZoneInfo.BaseUtcOffset.Seconds.ToString());
            oSB.AppendLine("        Ticks: " + oTimeZoneInfo.BaseUtcOffset.Ticks.ToString());
            oSB.AppendLine("        TotalDays: " + oTimeZoneInfo.BaseUtcOffset.TotalDays.ToString());
            oSB.AppendLine("        TotalHours: " + oTimeZoneInfo.BaseUtcOffset.TotalHours.ToString());
            oSB.AppendLine("        TotalMilliseconds: " + oTimeZoneInfo.BaseUtcOffset.TotalMilliseconds.ToString());
            oSB.AppendLine("        TotalMinutes: " + oTimeZoneInfo.BaseUtcOffset.TotalMinutes.ToString());
            oSB.AppendLine("        TotalSeconds: " + oTimeZoneInfo.BaseUtcOffset.TotalSeconds.ToString());
            oSB.AppendLine("    IsDaylightSavingTime: " + oTimeZoneInfo.IsDaylightSavingTime(oDateTime).ToString());
            oSB.AppendLine("    IsAmbiguousTime: " + oTimeZoneInfo.IsAmbiguousTime(oDateTime).ToString());
            if (oTimeZoneInfo.IsAmbiguousTime(oDateTime) == true)
            {
                DateTime oDT = TimeZoneInfo.ConvertTime(oDateTime, oTimeZoneInfo);
                oSB.AppendLine(ResolveAmbiguousTime(oDateTime, oTimeZoneInfo));
            }


            oSB.AppendLine("    IsInvalidTime: " + oTimeZoneInfo.IsInvalidTime(oDateTime).ToString());
            //if (oTimeZoneInfo.IsInvalidTime(oDateTime) == true)
            //{
            //    oSB.AppendLine(GetPossibleUtcTimes(oTimeZoneInfo, oDateTime));
            //}

            oSB.AppendLine("    ToSerializedString: " + oTimeZoneInfo.ToSerializedString());
            oSB.AppendLine(" ");

            oSB.AppendLine(GetAdjustmentRules(oTimeZoneInfo));

            //oSB.AppendLine("  AdjustmentRules:");
            //foreach (TimeZoneInfo.AdjustmentRule ars in oTimeZoneInfo.GetAdjustmentRules())
            //{
            //    oSB.AppendLine("    Adjustment Rule:   DateStart: " + ars.DateStart.ToString()  + "   DateEnd: " + ars.DateEnd.ToString());
            //    oSB.AppendLine("        DaylightTransitionStart: ");
            //    oSB.AppendLine("            Month: " + ars.DaylightTransitionStart.Month.ToString());
            //    oSB.AppendLine("            Day: " + ars.DaylightTransitionStart.Day.ToString());
            //    oSB.AppendLine("            DayOfWeek: " + ars.DaylightTransitionStart.DayOfWeek.ToString());
            //    oSB.AppendLine("            TimeOfDay: " + ars.DaylightTransitionStart.TimeOfDay.ToString());
            //    oSB.AppendLine("            Week: " + ars.DaylightTransitionStart.Week.ToString());
            //    oSB.AppendLine("            IsFixedDateRule: " + ars.DaylightTransitionStart.IsFixedDateRule.ToString());
            //    oSB.AppendLine("        DaylightTransitionEnd: ");
            //    oSB.AppendLine("            Month: " + ars.DaylightTransitionEnd.Month.ToString());
            //    oSB.AppendLine("            Day: " + ars.DaylightTransitionEnd.Day.ToString());
            //    oSB.AppendLine("            DayOfWeek: " + ars.DaylightTransitionEnd.DayOfWeek.ToString());
            //    oSB.AppendLine("            TimeOfDay: " + ars.DaylightTransitionEnd.TimeOfDay.ToString());
            //    oSB.AppendLine("            Week: " + ars.DaylightTransitionEnd.Week.ToString());
            //    oSB.AppendLine("            IsFixedDateRule: " + ars.DaylightTransitionEnd.IsFixedDateRule.ToString());
            //    oSB.AppendLine("        DaylightDelta: " + ars.DaylightDelta.ToString());

            //}
            oSB.AppendLine(" ");

            oSB.AppendLine("    GetAmbiguousTimeOffsets:");
            if (oTimeZoneInfo.IsAmbiguousTime(oDateTime) == false)
            {
                oSB.AppendLine("        The time is not Ambiguous for ths timezone.");
            }
            else
            {
                foreach (TimeSpan oTzTimeSpan in oTimeZoneInfo.GetAmbiguousTimeOffsets(oDateTime))
                {
                    oSB.AppendLine("    TimeSpan: " + oTzTimeSpan.ToString());
                    oSB.AppendLine("        Days: " + oTzTimeSpan.Days.ToString());
                    oSB.AppendLine("        Hours: " + oTzTimeSpan.Hours.ToString());
                    oSB.AppendLine("        Milliseconds: " + oTzTimeSpan.Milliseconds.ToString());
                    oSB.AppendLine("        Minutes: " + oTzTimeSpan.Minutes.ToString());
                    oSB.AppendLine("        Seconds: " + oTzTimeSpan.Seconds.ToString());
                    oSB.AppendLine("        Ticks: " + oTzTimeSpan.Ticks.ToString());
                    oSB.AppendLine("        TotalDays: " + oTzTimeSpan.TotalDays.ToString());
                    oSB.AppendLine("        TotalHours: " + oTzTimeSpan.TotalHours.ToString());
                    oSB.AppendLine("        TotalMilliseconds: " + oTzTimeSpan.TotalMilliseconds.ToString());
                    oSB.AppendLine("        TotalMinutes: " + oTzTimeSpan.TotalMinutes.ToString());
                    oSB.AppendLine("        TotalSeconds: " + oTzTimeSpan.TotalSeconds.ToString());
                }
            }

            oSB.AppendLine(" ");

            //// http://msdn.microsoft.com/en-us/library/bb495915(v=vs.110).aspx
            //// Convert to local time
            oSB.AppendLine("****************************");

            oSB.AppendLine("Test convert to Local ****");
            try
            {
                DateTime localTime = TimeZoneInfo.ConvertTime(oDateTime, oTimeZoneInfo, TimeZoneInfo.Local);
                oSB.AppendLine("    In Local: ");
                oSB.AppendLine("        DateTime: " + localTime.ToString());
                oSB.AppendLine("        IsDaylightSavingTime: " + TimeZoneInfo.Local.IsDaylightSavingTime(localTime).ToString());
                oSB.AppendLine(" ");
            }
            catch (Exception exConvertLocal)
            {
                oSB.AppendLine(" ");
                oSB.AppendLine("****************");
                oSB.AppendLine("    Error trying to use TimeZoneInfo.ConvertTime to convert timezone to Local time using spedified DateTime");
                oSB.AppendLine("    " + exConvertLocal.ToString());
                oSB.AppendLine("    ****************");
                oSB.AppendLine(" ");
            }
            oSB.AppendLine("**************************");
            oSB.AppendLine(" ");

            oSB.AppendLine("****************************");
            oSB.AppendLine("Test convert to UTC");
            try
            {
                // Convert to UTC
                DateTime utcTime = TimeZoneInfo.ConvertTime(oDateTime, oTimeZoneInfo, TimeZoneInfo.Utc);
                oSB.AppendLine("    In UTC - ConvertTime: ");
                oSB.AppendLine("        DateTime: " + utcTime);
                oSB.AppendLine("        IsDaylightSavingTime: " + TimeZoneInfo.Local.IsDaylightSavingTime(utcTime).ToString());
                oSB.AppendLine(" ");
            }
            catch (Exception exConvertLocal)
            {
                oSB.AppendLine(" ");
                oSB.AppendLine("    ****************");
                oSB.AppendLine("    Error trying to use TimeZoneInfo.ConvertTime to convert timezone to UTC time using spedified DateTime");
                oSB.AppendLine("    " + exConvertLocal.ToString());
                oSB.AppendLine("    ****************");
                oSB.AppendLine(" ");
            }
            oSB.AppendLine("**************************");
            oSB.AppendLine(" ");

            s = oSB.ToString();

            return(s);
        }
Beispiel #13
0
        public static TimeSpan GetOtherAmbigousOffset(this TimeZoneInfo timeZone, DateTimeOffset value)
        {
            var list = timeZone.GetAmbiguousTimeOffsets(value);

            return(list[0] == value.Offset ? list[1] : list[0]);
        }
        public DateTime NextUtc(DateTime dateTimeUtc)
        {
            if (dateTimeUtc.Kind != DateTimeKind.Utc)
            {
                throw new ArgumentException("Only UTC times can be used", nameof(dateTimeUtc));
            }

            var truncatedUtc = dateTimeUtc.TruncateMs();

            var dateTime = TimeZoneInfo.ConvertTimeFromUtc(truncatedUtc, _timeZoneInfo);

            var offsets = new List <TimeSpan>();

            if (_timeZoneInfo.IsAmbiguousTime(dateTime))
            {
                offsets.AddRange(_timeZoneInfo.GetAmbiguousTimeOffsets(dateTime));
            }
            else
            {
                offsets.Add(_timeZoneInfo.GetUtcOffset(dateTime));
            }

            var possibleResults = new List <DateTime?>();

            DateTime nextDateTime, originalDateTime;

            foreach (var offset in offsets)
            {
                nextDateTime = originalDateTime = DateTime.SpecifyKind(truncatedUtc.Add(offset), DateTimeKind.Unspecified);

                DoNext(ref nextDateTime, nextDateTime.Year);

                if (nextDateTime == originalDateTime)
                {
                    // We arrived at the original timestamp - round up to the next whole second and try again...
                    nextDateTime = nextDateTime.AddSeconds(1);
                    DoNext(ref nextDateTime, nextDateTime.Year);
                }

                // try to skip invalid time for the time zone
                while (_timeZoneInfo.IsInvalidTime(nextDateTime))
                {
                    nextDateTime = nextDateTime.AddSeconds(1);
                    DoNext(ref nextDateTime, nextDateTime.Year);
                }

                if (_timeZoneInfo.IsAmbiguousTime(nextDateTime))
                {
                    var nextOffsets = _timeZoneInfo.GetAmbiguousTimeOffsets(nextDateTime);

                    if (_isIntervalBased)
                    {
                        foreach (var nextOffset in nextOffsets)
                        {
                            possibleResults.Add(DateTime.SpecifyKind(nextDateTime.Subtract(nextOffset), DateTimeKind.Utc));
                        }
                    }
                    else
                    {
                        // if the expression is not interval based (doesn't have */- in sec, min, hour field)
                        // we only use one of the intervals (the last one), which has the largest offset and yields smallest time after subtract.
                        possibleResults.Add(DateTime.SpecifyKind(nextDateTime.Subtract(nextOffsets.Last()), DateTimeKind.Utc));
                    }
                }
                else
                {
                    var nextOffset = _timeZoneInfo.GetUtcOffset(nextDateTime);
                    possibleResults.Add(DateTime.SpecifyKind(nextDateTime.Subtract(nextOffset), DateTimeKind.Utc));
                }
            }

            return(possibleResults
                   .OrderBy(utc => utc)
                   .FirstOrDefault(utc => utc > dateTimeUtc)
                   ?? throw new Exception("Possible bug in code - couldn't find next cron time"));
        }