C# 在C中将DST规则转换为DateTime#
我有这样的DST规则: “2,-11.36亿”C# 在C中将DST规则转换为DateTime#,c#,datetime,timezone,dst,C#,Datetime,Timezone,Dst,我有这样的DST规则: “2,-11.36亿” 2是以零为基的月份 -1是包含日期的周数,-1是包含日期的月份的最后一周 1是一周中的一天,从1号星期天到7号星期六 3600000是从指定日期的午夜开始的毫秒,DST的变更将发生,并以包括DST在内的当地时间表示,因此DST切换时间的结束以DST表示 在C#DateTime中转换它的正确方法是什么 到目前为止,我已经做到了: public static DateTime ConvertDstRule(int year, string rule
- 2是以零为基的月份
- -1是包含日期的周数,-1是包含日期的月份的最后一周
- 1是一周中的一天,从1号星期天到7号星期六
- 3600000是从指定日期的午夜开始的毫秒,DST的变更将发生,并以包括DST在内的当地时间表示,因此DST切换时间的结束以DST表示
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;
}
publicstaticdatetime-convertdsrule(int-year,string规则,bool-isEndRule)
{
const int DaysInWeek=7;
var ruleName=isEndRule?“endRule”:“startRule”;
var startStrings=rule.Split(',');
var月=转换为32(起始字符串[0]);
如果((月<0)| |(月>11))
{
抛出新ArgumentOutOfRangeException(ruleName,“月值必须介于0和11之间”);
}
var week=转换为32(开始字符串[1]);
如果((周<-1)| |(周>5))
{
抛出新ArgumentOutOfRangeException(ruleName,“周值必须介于-1和5之间”);
}
if((转换为32(起始字符串[2])<1)| |(转换为32(起始字符串[2])>7))
{
抛出新ArgumentOutOfRangeException(ruleName,“日期值必须介于1和7之间”);
}
var day=(DayOfWeek)(Convert.ToInt32(startString[2])-1);//DayOfWeek是基于零的,所以移位1。
var timeOffset=Convert.ToInt64(startStrings[3]);
如果((时间偏移/1000/60)>86400)
{
抛出新ArgumentOutOfRangeException(ruleName,“时间偏移限制为一天”);
}
//找到相关年份的开始。
var startTime=新日期时间(年,1,1);
//添加月份以到达所选月份的开始。
startTime=startTime.AddMonths(月);
//如果本周为负数,则转到本周当天的第一个事件
//下个月,增加一个负的周数将跳回
//上个月。
如果(周<0)
{
startTime=startTime.AddMonths(1);
}
其他的
{
周=第1周;
}
//跳转到当月要切换的第一个事件。
var monthStartsOn=startTime.DayOfWeek;
var daysToSwitchDay=(整数)天-(整数)月开始;
//这可能是负面的,因为大多数区域在周日切换
if(daysToSwitchDay<0)
{
daysToSwitchDay=DaysInWeek+daysToSwitchDay;//daysToSwitchDay为负数,因此添加它。
}
startTime=startTime.AddDays(daysToSwitchDay);//现在是正确的一天。
startTime=startTime.AddDays(周*7);//周从1开始计数。
startTime=startTime.add毫秒(时间偏移);
如果(isEndRule)
{
startTime=startTime.AddHours(-1);//去掉DST小时,将其转换为UTC。
}
返回起始时间;
}
它是否考虑了半小时DST的变化,比如在印度?你能找出这段代码中的错误吗?有几点:
- 您描述的输入类型称为“转换规则”。或者在时区之外,它是一种特殊类型的“重复规则”。它简单地描述了一种模式,用于根据月份、星期和工作日确定特定时间点在给定年份的发生时间
- 转换规则不会告诉您计算时区值所需的所有信息。特别是,它不会告诉您在转换之前或之后与UTC的偏移量是多少,也不会告诉您偏移量的调整方向。此外,您还需要一套这些,因为通常每年有两套,但也可以有任意数量的。例如,2014年,以及。同时考虑到这些规则随着时间的推移而改变,所以一条规则,甚至是一对规则,将不会告诉你如何及时转换所有时间点的值。对于给定的时区,您需要一组规则,这就是我们所说的“时区”的意思
- 在.NET Framework中,
类用于处理时区。它包含子类,TimeZoneInfo
和TimeZoneInfo.AdjustmentRule
。特别是,在TimeZoneInfo.TransitionTime
中有一个名为TimeZoneInfo
的内部函数,它完全满足您的要求。它需要TransitionTimeToDateTime
和一年,并提供一年内发生转换的TransitionTime
。你可以找到这个DateTime
- 使用问题注释的建议是一个很好的建议,但不幸的是,野田佳彦没有任何特定的API来解释单一的转换规则。相反,建议您使用现有的TZDB区域,例如
。或者,您可以使用“America/New_York”