我试图构建一个逻辑的时区记录集,表示一个5年的时间,其中停止和开始日期/时间与人们所认为的时间变化时刻夏时制相匹配。例如,在美国/纽约id中,我希望:
03/13/2016 2:00 am - 11/06/2016 01:59:59 am gmtOffset: -4:00
11/06/2016 2:00 am - 03/12/2017 01:59:59 am gmtOffset: -5:00我能够建立这些记录,但我没有别的办法,只有在1912年dst生效之前开始,并跟踪所有区域间隔的结束时间。我不认为有一种方法可以在间隔记录周期开始时确定偏移量,而不是以前的间隔记录。是否有一种方法只使用一个ZoneInterval记录就可以做到这一点?
守则中指出的问题:
private void processTZ()
{
IDateTimeZoneProvider provider = DateTimeZoneProviders.Tzdb;
using (StreamWriter sw = new StreamWriter(@"c:\tzOut.txt"))
{
foreach (string id in provider.Ids)
{
sw.WriteLine("Id: {0}", id);
DateTimeZone zone = provider[id];
// Time period I wish to create logical representation.
Instant instantValidityBegin = (new LocalDateTime(2014, 1, 1, 0, 0)).InZoneLeniently(zone).ToInstant();
Instant instantValidityEnd = (new LocalDateTime(2019, 12, 31, 23, 59, 59, 0)).InZoneLeniently(zone).ToInstant();
// Time period from zone intervals to iterate. The first year dst was observed was 1916.
Instant instantFetchYearBegin = (new LocalDateTime(1916, 1, 1, 0, 0)).InZoneLeniently(zone).ToInstant();
Instant instantFetchYearEnd = (new LocalDateTime(2019, 12, 31, 23, 59, 0)).InZoneLeniently(zone).ToInstant();
// Get the intervals
IEnumerable<NodaTime.TimeZones.ZoneInterval> intervals = zone.GetZoneIntervals(instantFetchYearBegin, instantFetchYearEnd);
// Determine number of intervals for this tzId.
int count = 0;
foreach (NodaTime.TimeZones.ZoneInterval zi in intervals)
count++;
bool singleEntry = (1 == count);
// myStart and myEnd are desired output period
// capture IsoLocalEnd of an interval to be used as the start date of program output (myStart). Don't display older than 1900.
DateTime myStart, myEnd, prevEnd = new DateTime(1900, 1, 1);
foreach (NodaTime.TimeZones.ZoneInterval zi in intervals)
{
if (singleEntry)
{
// No question here
}
else
{
// skip intervals for this tzId that represent a period beginning after time period I want.
if (instantValidityEnd < zi.Start)
break;
// Skip intervals ending prior to time period I want, but capture the IsoLocalEnd to be used for report output.
if (zi.End < instantValidityBegin)
{
prevEnd = (zi.End == Instant.MinValue) ? prevEnd = new DateTime(1900, 1, 1) : prevEnd = zi.IsoLocalEnd.ToDateTimeUnspecified(); ;
continue;
}
// ***Question*** Can this myStart value be determined using the current interval record instead of storing the previous interval's IsoLocalEnd??
myStart = prevEnd;
if (zi.End == Instant.MaxValue)
prevEnd = myEnd = new DateTime(9999, 12, 31);
else
{
prevEnd = zi.IsoLocalEnd.ToDateTimeUnspecified();
myEnd = prevEnd.Subtract(TimeSpan.FromSeconds(1)); // force period back 1 second for logical representation.
}
sw.WriteLine("Name: " + zi.Name);
sw.WriteLine("Multi Entry: {0}", zi.ToString());
sw.WriteLine("myStart: {0:G} myEnd: {1:G} gmtOffset: {2:G}", myStart, myEnd, zi.WallOffset.ToTimeSpan());
sw.WriteLine();
}
}
sw.WriteLine("------------------------------------------------------------------");
sw.WriteLine();
}
}
}发布于 2016-05-23 03:48:41
在任何给定的ZoneInterval记录上,IsoLocalStart和IsoLocalEnd都是相对于该特定间隔的,对两者使用相同的WallOffset值。
如果您想获得实际的本地时间,您可以使用Start和End实例并将它们转换到特定的时区。
zi.Start.InZone(zone)
zi.End.InZone(zone)您会发现起始值的LocalDateTime与IsoLocalStart匹配,但结束值不匹配。当观察到瞬间时,它现在被下一个间隔的偏移所覆盖。别忘了这是半开放的间隔。[inclusive-start, exclusive-end)。
让我们回到原始请求中的示例:
2016年03月13日2:00 - 11/06/2016 01:59:59 gmtOffset:-4:00 11/06/2016 2:00 - 03/12/2017 01:59:59 gmtOffset:-5:00 gmtOffset:-5:00
它不是那样工作的。三月份,当地时间从1:59:59 am转到3:00:00 am,跳过了一个多小时。所以第一行应该从3:00 am开始,而不是从2:00 am开始。去年11月,当地时间从01:59:59 am转到了1:00:00 am,重复了一个小时。因此,第二行应该从1:00 am而不是2:00 am开始。您的图表似乎试图使本地时间连续--但事实并非如此。
此外,你会发现,按照惯例,许多人认为转换的时间是2:00,而不是1:59:59。把它想象成接近2点。这就是为什么向IsoLocalEnd显示当前间隔的偏移量,您可以将该字段用于此目的。
另外,您可能需要查看如何timeanddate.com显示的内容。他们决定只显示结束值,这可能会使事情变得更清楚一些。
https://stackoverflow.com/questions/37328727
复制相似问题