将DST规则转换为c#中的日期时间



我有这样的夏令时规则:

" 2 1 1 3600000"

  • 2是从零开始的月份
  • -1表示包含天的周数,-1表示包含天的月份的最后一周。
  • 1为一周中的一天,1 -周日至7 -周六
  • 3600000为从指定日期的午夜开始转换夏令时的毫秒数,用包括夏令时在内的当地时间表示,因此夏令时转换结束时间为夏令时。

在c# DateTime中转换它的正确方法是什么?

到目前为止,我已经完成了:

public static DateTime ConvertDstRule(int year, string rule, bool isEndRule)
{
    const int DaysInWeek = 7;
    var ruleName = isEndRule ? "endRule" : "startRule";
    var startStrings = rule.Split(',');
    var month = Convert.ToInt32(startStrings[0]);
    if ((month < 0) || (month > 11))
    {
        throw new ArgumentOutOfRangeException(ruleName, "The month value must be between 0 and 11");
    }
    var week = Convert.ToInt32(startStrings[1]);
    if ((week < -1) || (week > 5))
    {
        throw new ArgumentOutOfRangeException(ruleName, "The week value must be between -1 and 5");
    }
    if ((Convert.ToInt32(startStrings[2]) < 1) || (Convert.ToInt32(startStrings[2]) > 7))
    {
        throw new ArgumentOutOfRangeException(ruleName, "The day value must be between 1 and 7");
    }
    var day = (DayOfWeek)(Convert.ToInt32(startStrings[2]) - 1); // DayOfWeek is zero based so shift by one.
    var timeOffset = Convert.ToInt64(startStrings[3]);
    if ((timeOffset / 1000 / 60) > 86400)
    {
        throw new ArgumentOutOfRangeException(ruleName, "The time offset is limited to one day");
    }
    // Find the start of the relevant year.
    var startTime = new DateTime(year, 1, 1);
    // Add on the month to get to the start of the selected month.
    startTime = startTime.AddMonths(month);
    // If the week is negative then go to the first occurance of the day in
    // the next month, adding a negative week number will jump back into
    // the previous month.
    if (week < 0)
    {
        startTime = startTime.AddMonths(1);
    }
    else
    {
        week = week - 1;
    }
    // Jump to the first occurence of the day to switch in that month.
    var monthStartsOn = startTime.DayOfWeek;
    var daysToSwitchDay = (int)day - (int)monthStartsOn;
    // This is likely to be negative as most zones switch on a Sunday
    if (daysToSwitchDay < 0)
    {
        daysToSwitchDay = DaysInWeek + daysToSwitchDay; // daysToSwitchDay is negative so add it.
    }
    startTime = startTime.AddDays(daysToSwitchDay); // Now on the correct day.
    startTime = startTime.AddDays(week * 7); // Week counts from 1.
    startTime = startTime.AddMilliseconds(timeOffset);
    if (isEndRule)
    {
        startTime = startTime.AddHours(-1); // Take off the DST hour to convert it to UTC.
    }
    return startTime;
}

它是否像印度那样考虑到半小时的夏时制变化?你能发现这段代码中的错误吗?

几点:

  • 您所描述的输入类型称为"过渡规则"。或者在时区上下文之外,它是一种特殊类型的"递归规则"。它简单地描述了一种模式,用于根据月、周和工作日确定给定年份中的特定时间点。

  • 一个转换规则并不能告诉你计算时区值所需要知道的一切。特别是,它不会告诉你在转换之前或之后与UTC的偏移量是什么,或者偏移量被调整的方向。此外,您还需要一组,因为每年通常有两个这样的文件,但也可以有任意数量的文件。例如,2014年,俄罗斯只有一次过渡,埃及有四次。还要考虑到这些规则随着时间的推移而改变,因此单个规则,甚至一对规则,不会告诉您如何转换所有时间点的值。对于给定的时区,您需要一组规则集,这就是我们所说的"时区"。

  • 在。net框架中,TimeZoneInfo类用于处理时区。它包含子类TimeZoneInfo.AdjustmentRuleTimeZoneInfo.TransitionTime。特别地,在TimeZoneInfo中有一个内部函数叫做TransitionTimeToDateTime,它做的正是你想要的。它需要TransitionTime和一年,然后给你DateTime,转换在一年内发生。你可以在。net参考源代码中找到

但是,如果您真的想尝试从自己的数据源中实现时区规则,则应该考虑以下几点:

  1. 你真的认为你能比你之前的几百个人做得更好吗?也许是这样,但不要抱着"这很简单"的态度。我建议你看这个短视频,并在尝试之前做大量的研究。

  2. 您是否在考虑如何保持事物的维护?时区规则经常变化。每年,世界范围内大约会有十几个变化。您是否计划监控新闻提要、论坛、政府新闻稿和其他来源?当政府没有给出夏令时规则将要改变的警告时,你准备好采取行动了吗?

  3. 当事情不准确时,它会对你的系统产生多大的影响?它可以是不重要的(例如:博客或论坛),也可以是重要的(例如:航班时刻表、通信、医疗、金融等)。

另外

:

  • 从问题的评论中使用Noda Time的建议是一个很好的建议,但不幸的是Noda Time没有任何特定的API来解释单一的转换规则。相反,最好使用现有的TZDB区域,如"America/New_York"。或者,你可以使用。net框架中的TimeZoneInfo类,其id为"Eastern Standard Time" .

  • 内部,Noda Time通过ZoneYearOffset类处理转换规则。您可以在此代码中看到TransitionRule如何映射到ZoneYearOffset

  • 在您的代码示例中,注释"Take off the DST hour to convert it to UTC."是高度误导性的。函数的输出是以本地时间表示的。UTC与此无关。您在这里展示的代码中没有其他地方跟踪UTC的偏移量,无论是否使用DST。我想你的意思是……将其转换为标准时间",但我不确定您为什么要这样做。这个特殊的函数不应该试图解释这个

  • 你还问:"它是否考虑到像印度那样半小时的夏时制变化?"这个问题是无效的,因为印度没有夏令时。它的标准时区偏移有半小时(UTC+05:30),但没有夏令时。目前世界上唯一使用半小时夏令时偏差的地方是豪勋爵岛(Lord Howe Island),它由tzdb中的"Australia/Lord_Howe"时区表示,目前没有对应的Windows时区。在世界其他地方(除了南极洲的几个研究站),如果使用夏时制,转换偏差为1小时。

相关内容

  • 没有找到相关文章