You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过时区ID获取夏令时起止日期?C#技术问询

获取指定时区的夏令时起止日期(不受服务器时区影响)

嘿,你已经用TimeZoneInfo.IsDaylightSavingTime搞定了夏令时判断,接下来要拿起止日期其实很简单——不过得先避开一个坑:TimeZone.GetDaylightChanges是绑定服务器本地时区的,不能直接用它来拿"GMT Standard Time"的规则。正确的姿势是用TimeZoneInfo自带的调整规则(AdjustmentRule),它能直接针对你指定的时区提取夏令时切换时间,完全不受服务器所在时区干扰。

核心思路

  • 通过TimeZoneInfo.GetAdjustmentRules()获取目标时区的所有夏令时规则(毕竟不同年份的规则可能会变)
  • 根据目标日期的年份,匹配对应的调整规则
  • 解析规则里的TransitionTime属性,得到夏令时的开始/结束日期(这些时间都是目标时区的本地时间)

修改后的完整代码

using System;
public class Program {
    public static void Main() {
        var myDate = new DateTime(2020, 5, 31, 11, 9, 0);
        var myTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
        bool isDaylightSavingTime = myTimeZoneInfo.IsDaylightSavingTime(myDate);
        Console.WriteLine(isDaylightSavingTime);

        if (isDaylightSavingTime) {
            // 获取该时区的所有夏令时调整规则
            var adjustmentRules = myTimeZoneInfo.GetAdjustmentRules();
            int targetYear = myDate.Year;
            AdjustmentRule matchedRule = null;

            // 找到目标年份对应的规则(规则是按日期范围划分的)
            foreach (var rule in adjustmentRules) {
                if (rule.DateStart.Year <= targetYear && rule.DateEnd.Year >= targetYear) {
                    matchedRule = rule;
                    break;
                }
            }

            if (matchedRule != null) {
                // 解析夏令时开始/结束的具体日期
                DateTime dstStart = GetTransitionDateTime(targetYear, matchedRule.DaylightTransitionStart, myTimeZoneInfo);
                DateTime dstEnd = GetTransitionDateTime(targetYear, matchedRule.DaylightTransitionEnd, myTimeZoneInfo);

                Console.WriteLine($"夏令时开始:{dstStart:yyyy-MM-dd HH:mm:ss} (GMT时区本地时间)");
                Console.WriteLine($"夏令时结束:{dstEnd:yyyy-MM-dd HH:mm:ss} (GMT时区本地时间)");
                
                // 如果需要转UTC,直接用下面的代码
                // DateTime dstStartUtc = TimeZoneInfo.ConvertTimeToUtc(dstStart, myTimeZoneInfo);
                // DateTime dstEndUtc = TimeZoneInfo.ConvertTimeToUtc(dstEnd, myTimeZoneInfo);
            } else {
                Console.WriteLine($"年份{targetYear}没有对应的夏令时调整规则");
            }
        }
    }

    // 辅助方法:把TransitionTime转换成具体的DateTime
    private static DateTime GetTransitionDateTime(int year, TransitionTime transition, TimeZoneInfo timeZone) {
        // 处理固定日期规则(比如每年3月25日)
        if (transition.IsFixedDateRule) {
            return new DateTime(year, transition.Month, transition.Day, transition.TimeOfDay.Hour, transition.TimeOfDay.Minute, transition.TimeOfDay.Second);
        } 
        // 处理相对日期规则(比如三月最后一个星期日)
        else {
            DateTime firstDayOfMonth = new DateTime(year, transition.Month, 1);
            // 计算当月第一个目标星期几的日期
            int daysToFirstTarget = ((int)transition.DayOfWeek - (int)firstDayOfMonth.DayOfWeek + 7) % 7;
            DateTime targetDay = firstDayOfMonth.AddDays(daysToFirstTarget);

            // 如果是"最后一个"星期几,就往后推到当月最后一个符合条件的日期
            if (transition.Week == 5) {
                while (targetDay.AddDays(7).Month == transition.Month) {
                    targetDay = targetDay.AddDays(7);
                }
            } 
            // 否则取第N个星期几
            else {
                targetDay = targetDay.AddDays((transition.Week - 1) * 7);
            }

            return targetDay.Add(transition.TimeOfDay);
        }
    }
}

关键细节说明

  • AdjustmentRule是按日期范围存储的,所以要先匹配目标年份对应的规则
  • TransitionTime分两种类型:固定日期和相对日期(比如"某月最后一个星期日"),辅助方法已经帮你处理了这两种情况
  • 得到的起止日期是目标时区的本地时间,如果需要转换成UTC,直接用TimeZoneInfo.ConvertTimeToUtc()即可

内容的提问来源于stack exchange,提问作者Femil Shajin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:07:32