C# 如何在.NET中的DST时间内获取UTC偏移量

C# 如何在.NET中的DST时间内获取UTC偏移量,c#,.net,datetime,utc,dst,C#,.net,Datetime,Utc,Dst,我试图在一个时区内,在一段时间间隔内看到所有偏移量。下面是我用来完成此任务的函数,我知道您可以使用TimeZoneInfo.BaseUtcOffset在标准时间内获取时区的UTC偏移量,但在夏令时没有类似的方法来获取偏移量,除非您将特定的DST时间点传递给GetUTCOffset()方法 static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz) { var result = new Hash

我试图在一个时区内,在一段时间间隔内看到所有偏移量。下面是我用来完成此任务的函数,我知道您可以使用
TimeZoneInfo.BaseUtcOffset
在标准时间内获取时区的
UTC偏移量
,但在夏令时没有类似的方法来获取偏移量,除非您将特定的
DST
时间点传递给
GetUTCOffset()
方法

static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz)
{
    var result = new HashSet<int>();
    var adjRules = tz.GetAdjustmentRules();
    result.Add(tz.BaseUtcOffset);

    foreach (var adjustmentRule in adjRules)
    {
        if ((startTime >= adjustmentRule.DateStart && startTime <= adjustmentRule.DateEnd) || (endTime >= adjustmentRule.DateStart && endTime <= adjustmentRule.DateEnd) ||
             (stTime <= adjustmentRule.DateStart && endTime >= adjustmentRule.DateEnd))
        {
            if(adjustmentRule.DaylightDelta != TimeSpan.Zero)
            {
                if (!result.Contains(tz.BaseUtcOffset + adjustmentRule.DaylightDelta))
                      result.Add((tz.BaseUtcOffset + adjustmentRule.DaylightDelta));
            }
         }
     }

     foreach (var res in result)
     {
         Console.WriteLine(res);
     }
}
static void getoffset(DateTime startTime、DateTime endTime、TimeZoneInfo tz)
{
var result=new HashSet();
var adjRules=tz.GetAdjustmentRules();
结果。添加(tz.BaseUtcOffset);
foreach(调整规则中的var调整规则)
{

如果((startTime>=adjustmentRule.DateStart&&startTime=adjustmentRule.DateStart&&endTime如果您正在做任何与日期有关的复杂事情,您应该查看一下(这是Joda Time Java库的一个端口)。它有一个完整的名称空间来处理棘手的时区问题。

我确实想出了这个方法来获得在指定时区信息的一年时间间隔内UTC间隔需要考虑的偏移量。我将此集合传递到数据库,以过滤UTC中保存的日期时间字段,用于间隔过滤器输入,如(“凌晨1点-凌晨2点”),我对系统中的所有时区都进行了测试,效果很好。虽然这不是我最初问题的答案,因为我仍在使用调整规则来获取偏移量,但这次我尝试使其可用

class Program
{
    static void Main(string[] args)
    {
        foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
        {
            var result = GetUTCOffsetsByUTCIntervals(1900, 2012, tz);
            Console.WriteLine(tz.DisplayName);
            foreach (var tuple in result)
            {
                Console.WriteLine(tuple.Item1 + "     " + tuple.Item2 + "   " + tuple.Item3);
            }
            Console.WriteLine("------------------------------------------------------------");
        }
        Console.Read();
    }

    public static List<Tuple<TimeSpan, DateTime, DateTime>> GetUTCOffsetsByUTCIntervals(int stYear, int endYear, TimeZoneInfo tz)
    {
        var cal = CultureInfo.CurrentCulture.Calendar;
        var offsetsByUTCIntervals = new List<Tuple<TimeSpan, DateTime, DateTime>>();
        var adjRules = tz.GetAdjustmentRules();
        for (var year = stYear; year <= endYear && year < DateTime.MaxValue.Year && year >= DateTime.MinValue.Year; year++)
        {
            var adjRule =
                adjRules.FirstOrDefault(
                    rule =>
                    rule.DateStart.Year == year || rule.DateEnd.Year == year ||
                    (rule.DateStart.Year < year && rule.DateEnd.Year > year));

            var yrStTime = new DateTime(year, 1, 1);
            var yrEndTime = yrStTime.AddYears(1).AddTicks(-1);

            if (adjRule != null)
            {
                var tStDate = GetTransitionDate(adjRule.DaylightTransitionStart, year);
                var tEnddate = GetTransitionDate(adjRule.DaylightTransitionEnd, year);

                var stTsp = adjRule.DaylightTransitionStart.TimeOfDay.TimeOfDay;

                var endTsp = adjRule.DaylightTransitionEnd.TimeOfDay.TimeOfDay;

                if (yrStTime.Date == tStDate && yrStTime.TimeOfDay == stTsp)
                    yrStTime = yrStTime.Add(adjRule.DaylightDelta);

                if (yrEndTime.Date == tEnddate && yrEndTime.TimeOfDay == endTsp)
                    yrEndTime = yrEndTime.Subtract(adjRule.DaylightDelta);

              if (tStDate.Month > tEnddate.Month)
                {
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks - 1), tz)));
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks - 1), tz)));
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(yrEndTime, tz))); 
                }
                else
                {
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks - 1), tz)));
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks - 1), tz)));
                    offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(yrEndTime, tz))); 
                }
            }
            else
            {
                offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(yrEndTime, tz)));
            }
        }
        return offsetsByUTCIntervals;
    }

    public static DateTime ConvertTimeToUtc(DateTime date, TimeZoneInfo timeZone)
    {
        if (date == null || timeZone == null)
        {
            return date;
        }
        DateTime convertedDate = TimeZoneInfo.ConvertTimeToUtc(date, timeZone);
        return convertedDate;
    }

    //copy from msdn http://msdn.microsoft.com/en-us/library/system.timezoneinfo.transitiontime.isfixeddaterule.aspx
    private static DateTime GetTransitionDate(TimeZoneInfo.TransitionTime transition, int year)
    {
        if (transition.IsFixedDateRule)
            return new DateTime(year, transition.Month, transition.Day);

        int transitionDay;
        var cal = CultureInfo.CurrentCulture.Calendar;
        var startOfWeek = transition.Week * 7 - 6;
        var firstDayOfWeek = (int)cal.GetDayOfWeek(new DateTime(year, transition.Month, 1));
        var changeDayOfWeek = (int)transition.DayOfWeek;

        if (firstDayOfWeek <= changeDayOfWeek)
            transitionDay = startOfWeek + (changeDayOfWeek - firstDayOfWeek);
        else
            transitionDay = startOfWeek + (7 - firstDayOfWeek + changeDayOfWeek);

        if (transitionDay > cal.GetDaysInMonth(year, transition.Month))
            transitionDay -= 7;
        return new DateTime(year, transition.Month, transitionDay);
    }

   /* static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz)
    {
        var result = new HashSet<string>();
        var adjRules = tz.GetAdjustmentRules();
        result.Add(tz.BaseUtcOffset.ToString());

        foreach (var adjustmentRule in adjRules)
        {
            if ((startTime >= adjustmentRule.DateStart && startTime <= adjustmentRule.DateEnd)
                    || (endTime >= adjustmentRule.DateStart && endTime <= adjustmentRule.DateEnd)
                 || (startTime <= adjustmentRule.DateStart && endTime >= adjustmentRule.DateEnd))
            {
                if(adjustmentRule.DaylightDelta != TimeSpan.Zero)
                {
                    if (!result.Contains((tz.BaseUtcOffset + adjustmentRule.DaylightDelta).ToString()))
                      result.Add((tz.BaseUtcOffset + adjustmentRule.DaylightDelta).ToString());
                }
            }
        }
        Console.Write(tz.DisplayName + "   ");
        foreach (var res in result)
        {
            Console.Write(res);
        }
    }*/
}
类程序
{
静态void Main(字符串[]参数)
{
foreach(TimeZoneInfo.GetSystemTimeZones()中的var tz)
{
var结果=GetutcoffsetsbyutcInterval(1900、2012、tz);
Console.WriteLine(tz.DisplayName);
foreach(结果中的变量元组)
{
Console.WriteLine(tuple.Item1+“”+tuple.Item2+“”+tuple.Item3);
}
Console.WriteLine(“-------------------------------------------------------------------------------------”);
}
Console.Read();
}
公共静态列表getutcoffsetsbyutcinterval(int-stYear、int-endYear、TimeZoneInfo-tz)
{
var cal=CultureInfo.CurrentCulture.Calendar;
var offsetsbyutcinterval=新列表();
var adjRules=tz.GetAdjustmentRules();
对于(var year=stYear;year=DateTime.MinValue.year;year++)
{
var调整规则=
adj.FirstOrDefault(
规则=>
rule.DateStart.Year==Year | | rule.DateEnd.Year==Year||
(rule.DateStart.YearYear));
var yrStTime=新日期时间(年,1,1);
var yrEndTime=yrStTime.AddYears(1.AddTicks(-1);
如果(adjRule!=null)
{
var tStDate=GetTransitionDate(adjRule.DaylightTransitionStart,年份);
var tEnddate=GetTransitionDate(adjRule.DaylightTransitionEnd,年份);
var stTsp=adjRule.DaylightTransitionStart.TimeOfDay.TimeOfDay;
var endTsp=adjRule.DaylightTransitionEnd.TimeOfDay.TimeOfDay;
if(yrStTime.Date==tStDate&&yrStTime.TimeOfDay==stTsp)
yrStTime=yrStTime.Add(adjRule.DaylightDelta);
如果(yrEndTime.Date==tEnddate&&yrEndTime.TimeOfDay==endTsp)
yrEndTime=yrEndTime.Subtract(adjRule.DaylightDelta);
如果(tStDate.Month>tEnddate.Month)
{
添加(新元组(tz.BaseUtcOffset+adjRule.DaylightDelta,ConvertTimeToUtc(yrStTime,tz),ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks-1),tz));
Add(新元组(tz.BaseUtcOffset,ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)),tz),ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks-1),tz));
Add(新元组(tz.BaseUtcOffset+adjRule.DaylightDelta,ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)),tz),ConvertTimeToUtc(yrEndTime,tz));
}
其他的
{
Add(新元组(tz.BaseUtcOffset,ConvertTimeToUtc(yrStTime,tz),ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks-1),tz));
Add(新元组(tz.BaseUtcOffset+adjRule.DaylightDelta),ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)),tz),ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks-1),tz));
Add(新元组(tz.BaseUtcOffset,ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)),tz),ConvertTimeToUtc(yrEndTime,tz));
}
}
其他的
{
Add(新元组(tz.BaseUtcOffset,ConvertTimeToUtc(yrStTime,tz),ConvertTimeToUtc(yrEndTime,tz));
}
}
返回偏移量间隔;
}
公共静态日期时间转换器TimeToutc(日期时间日期,时区信息时区)
{
如果(日期==null | |时区==null)
{
返回日期;
}
DateTime convertedDate=TimeZoneInfo.ConvertTimeToUtc(日期,时区);
返回转换日期;
}
//从msdn复制http://msdn.microsoft.com/en-us/library/system.timezoneinfo.transitiontime.isfixeddaterule.aspx
私有静态日期时间GetTransitionDate(TimeZoneInfo.TransitionTime转换,整数年)
{
if(transition.IsFixedDateRule)
返回新的日期时间(年、过渡期、月、过渡期、日);
国际过渡日;
var cal=CultureInfo.CurrentCulture.Calendar;
var startOfWeek=过渡周*7-6;
var firstDayOfWeek=(int)cal.GetDayOfWeek(新的日期时间(年、转换月份、1));
var changeDayOfWeek=(int)transition.DayOfWeek;
if(每周第一天cal.GetDaysInMonth(年,过渡月
public IEnumerable<ZoneInterval> GetZoneIntervalsInInterval
    (this DateTimeZone zone, Interval interval)
{
    Instant current = interval.Start;
    while (current < interval.End && current != Instant.MaxValue)
    {
        ZoneInterval zi = zone.GetZoneInterval(current);
        yield return zi;
        current = zi.End;
    }
}
var zone = BclDateTimeZone.FromTimeZoneInfo(tzInfo);
var offsets = zone.GetZoneIntervalsInInterval(interval)
                  .Select(zi => zi.WallOffset)
                  .Distinct();