Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Daylight Savings Time Start and End in NodaTime

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);
}
like image 476
Matt Kline Avatar asked Jun 23 '14 19:06

Matt Kline


People also ask

When did daylight savings time used to start and end?

The period would run from January 1974 to April 1975. The plan did little to save energy and in October 1974, the U.S. switched back to standard time. From 1987 through 2006, daylight saving time started the first weekend in April, running through the last weekend in October.

What does making daylight savings time permanent mean?

Permanent daylight saving time would keep the sun up later in the day, but would also mean the sun rises later. In the winter months that could mean some places won't see sunlight until as late as 9 a.m. Permanent standard time would end there still being daylight at 9 p.m. in heart of summer in Berks.

How does daylight savings work with time zones?

The simplest way to remember "time zone math" for the states that recognize Daylight saving time is three-two-one: three hours difference from Eastern to Pacific, two hours difference from Eastern to Mountain, and one hour difference from Eastern to Central.

What happens when time changes in November?

Today, most Americans spring forward (turn clocks ahead and lose an hour) on the second Sunday in March (at 2:00 A.M.) and fall back (turn clocks back and gain an hour) on the first Sunday in November (at 2:00 A.M.). See how your sunrise and sunset times will change with our Sunrise/set Calculator.


1 Answers

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 as 3/9/2014 3:00:00 AM and 11/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.

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 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.

like image 100
Matt Johnson-Pint Avatar answered Sep 27 '22 15:09

Matt Johnson-Pint