Getting Daytime for Start and End at NodaTime

How can I get the start and end dates for daylight saving time using Noda Time? The function below performs this task, but it is terribly cumbersome and asks for a simpler solution.

/// <summary> /// Gets the start and end of daylight savings time in a given time zone /// </summary> /// <param name="tz">The time zone in question</param> /// <returns>A tuple indicating the start and end of DST</returns> /// <remarks>Assumes this zone has daylight savings time</remarks> private Tuple<LocalDateTime, LocalDateTime> GetZoneStartAndEnd(DateTimeZone tz) { int thisYear = TimeUtils.SystemLocalDateTime.Year; // Get the year of the current LocalDateTime // Get January 1, midnight, of this year and next year. var yearStart = new LocalDateTime(thisYear, 1, 1, 0, 0).InZoneLeniently(tz).ToInstant(); var yearEnd = new LocalDateTime(thisYear + 1, 1, 1, 0, 0).InZoneLeniently(tz).ToInstant(); // Get the intervals that we experience in this year var intervals = tz.GetZoneIntervals(yearStart, yearEnd).ToArray(); // Assuming we are in a US-like daylight savings scheme, // we should see three intervals: // 1. The interval that January 1st sits in // 2. At some point, daylight savings will start. // 3. At some point, daylight savings will stop. if (intervals.Length == 1) throw new Exception("This time zone does not use daylight savings time"); if (intervals.Length != 3) throw new Exception("The daylight savings scheme in this time zone is unexpected."); return new Tuple<LocalDateTime,LocalDateTime>(intervals[1].IsoLocalStart, intervals[1].IsoLocalEnd); } 
+10
date c # dst nodatime
source share
2 answers

There is not a single built-in function that I know of, but all the data is there, so you can create your own.

You are on the right track with what you showed, but there are a few things to consider:

  • Usually people are interested in the endpoints of intervals. By returning the start and stop of only the middle interval, you are likely to get values ​​other than expected. For example, if you use one of the US time zones, for example, "America/Los_Angeles" , your function returns transitions like 3/9/2014 3:00:00 AM and 11/2/2014 2:00:00 AM , where you, probably expect 2:00 AM for both.

  • Time zones south of the equator that use DST will start it by the end of the year and finish it by the beginning of next year. Therefore, sometimes elements in a tuple can be undone from what you expect from them.

  • There are so many time zones that do not use daylight saving time, so throwing an exception is not a good idea.

  • There are at least two time zones that currently have four transitions in one year ( "Africa/Casablanca" and "Africa/Cairo" ) - with a “break” during their summertime periods for Ramadan. And sometimes there are transitions not related to DST, for example, when Samoa changed the standard deviation in 2011 , which gave it three transitions in one year.

Given all this, it would be better to return a list of points of one transition, rather than a set of pairs of transitions.

In addition, this is insignificant, but it would be better not to bind the method to the system clock at all. The year can be easily passed by parameter. Then you can use this method for non-current years, if necessary.

 public IEnumerable<LocalDateTime> GetDaylightSavingTransitions(DateTimeZone timeZone, int year) { var yearStart = new LocalDateTime(year, 1, 1, 0, 0).InZoneLeniently(timeZone).ToInstant(); var yearEnd = new LocalDateTime(year + 1, 1, 1, 0, 0).InZoneLeniently(timeZone).ToInstant(); var intervals = timeZone.GetZoneIntervals(yearStart, yearEnd); return intervals.Select(x => x.IsoLocalEnd).Where(x => x.Year == year); } 

Also, pay attention to the end, it is important to filter only the values ​​that are in the current year, because the intervals can be very extended to the next year or continue indefinitely.

+7
source share

This code snippet will also help you check for daylight saving time or not.

 public static bool IsDaylightSavingsTime(this DateTimeOffset dateTimeOffset) { var timezone = "Europe/London"; //https://nodatime.org/TimeZones ZonedDateTime timeInZone = dateTimeOffset.DateTime.InZone(timezone); var instant = timeInZone.ToInstant(); var zoneInterval = timeInZone.Zone.GetZoneInterval(instant); return zoneInterval.Savings != Offset.Zero; } 

how to use it

 var testDate = DateTimeOffset.Now; var isDst = testDate.IsDaylightSavingsTime(); 

Depends on your situation, you can change it a little

0
source share

All Articles