获取夏令时的开始和结束时间在NodaTime中

问题描述 投票:10回答:2

如何使用Noda Time获取夏令时的开始和结束日期?下面的函数可以完成此任务,但是它非常笨拙,并且正在寻求一个更简单的解决方案。

/// <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);
}
c# date dst nodatime
2个回答
7
投票

我不知道一个内置函数,但是数据就在那里,所以您当然可以创建自己的函数。

您所显示的内容处于正确的轨道,但需要考虑以下几点:

  • 通常人们对间隔的end点感兴趣。通过仅返回中间间隔的开始和停止,您可能会得到与期望值不同的值。例如,如果您使用美国时区之一,例如"America/Los_Angeles",则您的函数返回的过渡时间分别为3/9/2014 3:00:00 AM11/2/2014 2:00:00 AM,您可能都希望两者都为2:00 AM。

  • 赤道以南的使用DST的时区将在年底开始,到明年年初结束。因此,有时元组中的项目可能与您期望的相反。

  • 有很多时区不使用夏令时,所以抛出异常不是最好的主意。

  • 目前至少有两个时区在一年中有四个过渡("Africa/Casablanca""Africa/Casablanca")-斋月的夏令时中断。有时,存在与DST不相关的转换,例如"Africa/Cairo"何时在一年内实现了3转换。

考虑到所有这些因素,返回单个过渡点列表而不是返回成对的元组似乎更好。

另外,这是次要的,但是最好完全不将方法绑定到系统时钟。年份可以很容易地通过参数传递。然后,如有必要,您可以在非当前年份使用此方法。

"Africa/Cairo"

还请注意,重要的一点是仅过滤当年的值,因为间隔很可能会延续到下一年,或无限期地继续。


0
投票

此代码段代码还可以帮助您检查时间是否处于夏令时

Samoa changed its standard offset in 2011

使用方法

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);
}

根据您的情况,可以稍作修改

© www.soinside.com 2019 - 2024. All rights reserved.