How can I get the starting and ending dates for Daylight Savings Time using Noda Time? The function below accomplishes this task but it is horribly unwieldy and is begging 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);
}
This snippet code also help you to check a time is in daylightsavingstime or not
how to use it
Depend on your situation, you can modify it a bit
There's not a single built-in function that I am aware of, but the data is all there, so you can certainly create your own.
You're on the right track with what you've shown, but there are a few things to consider:
Normally people are interested in the end points of the intervals. By returning the start and stop of only the middle interval, you are likely getting values different than you expect. For example, if you use one of the US time zones, such as
"America/Los_Angeles"
, your function returns the transitions as3/9/2014 3:00:00 AM
and11/2/2014 2:00:00 AM
, where you are probably expecting 2:00 AM for both.Time zones south of the equator that use DST will start it towards the end of the year, and end it towards the beginning of the next year. So sometimes the items in the tuple might be reversed from what you expect them to be.
There are quite a lot of time zones that don't use daylight saving time, so throwing an exception isn't the best idea.
There are at least two time zones that presently have four transitions in a single year (
"Africa/Casablanca"
and"Africa/Cairo"
) - having a "break" in their DST periods for Ramadan. And occasionally, there are non-DST-related transitions, such as when Samoa changed its standard offset in 2011, which gave it three transitions in a single year.Taking all of this into account, it would seem better to return a list of single transition points, rather than a tuple of pairs of transitions.
Also, this is minor, but it would be better form to not bind the method to the system clock at all. The year can easily be passed by parameter. Then you can use this method for non-current years if necessary.
Also note at the end, it's important to filter just the values that are in the current year because the intervals may very well extend into the following year, or go on indefinitely.