C# 在NodaTime中开始和结束夏令时
如何使用野田时间获取夏令时的开始和结束日期? 下面的函数完成了这个任务,但它非常笨拙,需要一个更简单的解决方案C# 在NodaTime中开始和结束夏令时,c#,date,dst,nodatime,C#,Date,Dst,Nodatime,如何使用野田时间获取夏令时的开始和结束日期? 下面的函数完成了这个任务,但它非常笨拙,需要一个更简单的解决方案 /// <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> /// <retur
/// <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);
}
//
///获取给定时区中夏令时的开始和结束时间
///
///讨论中的时区
///指示DST开始和结束的元组
///假定此分区具有夏令时
私有元组GetZoneStartAndEnd(DateTimeZone tz)
{
int thiswear=TimeUtils.SystemLocalDateTime.Year;//获取当前LocalDateTime的年份
//今年和明年的1月1日午夜。
var yearStart=newlocaldatetime(今年,1,1,0,0).inzonelinely(tz).ToInstant();
var yearEnd=新的LocalDateTime(thisYear+1,1,0,0);
//获取我们今年经历的时间间隔
var interval=tz.GetZoneIntervals(yearStart,yearEnd).ToArray();
//假设我们在一个类似美国的夏令时计划中,
//我们应该看到三个间隔:
//1.1月1日所在的时间间隔
//2.在某个时候,夏令时将开始。
//在某个时候,夏令时将停止。
if(interval.Length==1)
抛出新异常(“此时区不使用夏令时”);
如果(间隔长度!=3)
抛出新的异常(“此时区的夏令时计划是意外的。”);
返回新元组(间隔[1]。IsoLocalStart,间隔[1]。ISOLOCALAND);
}
据我所知,没有一个内置函数,但数据都在那里,因此您当然可以创建自己的函数
您所展示的内容是正确的,但有几件事需要考虑:
- 通常人们对间隔的终点感兴趣。通过仅返回中间间隔的开始和停止,您可能会得到与预期不同的值。例如,如果您使用一个美国时区,例如
,则函数将转换返回为“America/Los_Angeles”
和3/9/2014 3:00:00 AM
,您可能希望这两个时区都是凌晨2:0011/2/2014 2:00:00 AM
- 赤道以南使用DST的时区将在年底开始,在明年初结束。因此,有时元组中的项可能与您期望的相反
- 有相当多的时区不使用夏令时,所以抛出异常不是最好的主意
- 目前,至少有两个时区在一年内(和)有四次转换——在斋月的DST期间有一次“休息”。偶尔也会有一些与DST无关的转换,比如when,它在一年内完成了三次转换
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);
}
public IEnumerable GetDaylightSavingTransitions(日期时区时区,整数年)
{
var yearStart=newlocaldatetime(year,1,1,0,0).inzonelinely(timeZone).ToInstant();
var yearEnd=newlocaldatetime(year+1,1,0,0);
var间隔=时区。GetZoneIntervals(年开始,年结束);
返回间隔。选择(x=>x.IsoLocalEnd)。其中(x=>x.Year==Year);
}
最后还要注意,只过滤当前年份中的值很重要,因为间隔很可能延伸到下一年,或者无限期地延续下去。此代码片段还可以帮助您检查时间是否在daylightsavingstime
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();
根据您的情况,您可以稍微修改它这是简单的bool-IsDaylightSavings(DateTimeZone-timeZone,Instant-Instant)方法的正确基础,还是有更好的方法?您的方法做什么?野田佳彦的文档不容易理解。我不知道什么是
IsoLocalEnd
,也不知道如何使用它来获取DST过渡时间。@方位角-根据文档,一个ZoneInterval
“表示一个特定偏移应用的时间范围”及其属性返回间隔的本地开始时间,如ISO日历中的LocalDateTime
。这不包括任何夏令时。这是半开放的时间间隔,因此这为我们提供了转换发生的本地时间。例如,在美国,我们刚刚进行了后退转换,我们通常说“在本地时间2:00,回到本地时间1:00”。实际上,这是“当时钟接近2:00时”“。如果你实际上是在2:00,那么转换已经发生在一个小时之前。但当我们要求过渡时,这仍然是我们感兴趣的2:00时间。因此,我们需要区域间隔的IsoLocalEnd
值。不幸的是,他们的文档远非易懂。。。