如何使用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);
}
答案 0 :(得分:7)
我所知道的没有一个内置函数,但数据就在那里,所以你当然可以创建自己的函数。
你已经走上了正确的道路,但有几点需要考虑:
通常人们对间隔的 end 点感兴趣。通过仅返回中间间隔的开始和停止,您可能会获得与预期不同的值。例如,如果您使用其中一个美国时区,例如"America/Los_Angeles"
,则您的函数会将转换返回为3/9/2014 3:00:00 AM
和11/2/2014 2:00:00 AM
,您可能希望它们在凌晨2:00
使用夏令时赤道以南的时区将在年底开始,并在明年年初结束。因此,有时元组中的项目可能会与您期望的项目相反。
有很多时区不使用夏令时,所以抛出异常不是最好的主意。
目前至少有两个时区在一年内有四个过渡期("Africa/Casablanca"
和"Africa/Cairo"
) - 在斋月的DST期间有一个“休息”。偶尔也有非DST相关的转换,例如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);
}
另请注意,最后,仅过滤当前年份的值非常重要,因为间隔可能会很好地延伸到下一年,或者无限期地继续。
答案 1 :(得分:0)
此代码段代码还可以帮助您检查时间是否处于夏令时
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;
}
使用方法
var testDate = DateTimeOffset.Now;
var isDst = testDate.IsDaylightSavingsTime();
根据您的情况,可以对其进行一些修改