ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

.NET 时区处理实战指南:awesome-copilot dotnet-timezone 技能解读与跨平台最佳实践

2026/9/13 16:41:05 拓冰建站 浏览量
.NET 时区处理实战指南:awesome-copilot dotnet-timezone 技能解读与跨平台最佳实践 .NET 时区处理实战指南awesome-copilot dotnet-timezone 技能解读与跨平台最佳实践【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot本篇技术指南围绕开源仓库 awesome-copilot 中的dotnet-timezoneAgent Skill 展开系统讲解 .NET / C# 应用在生产环境下处理时区的完整方法论从地址与位置到时区 ID 的解析、Windows 与 IANA 时区 ID 的跨平台映射、七大可复制代码模式TimeZoneInfo/TimeZoneConverter/NodaTime/DateTimeOffset/ ASP.NET Core 持久化与展示 / 定时调度 / DST 边界时间以及常见陷阱与决策指南。读完本文你将获得一套可直接落地到实际 .NET 项目中的时区处理方案并理解其底层原理与适用边界。技能定位dotnet-timezone 解决什么问题dotnet-timezone是 awesome-copilot 仓库中一个面向 .NET 与 C# 开发的 Agent Skill。根据其 SKILL.md 的定义它专门用于处理TimeZoneInfo、DateTimeOffset、NodaTime、UTC 转换、夏令时DST、跨时区调度以及 Windows / IANA 时区 ID 的跨平台兼容问题当 .NET 用户需要根据城市、地址、地区或国家获取对应时区并得到可直接复制粘贴的 C# 代码时该技能会给出生产级安全建议。在 awesome-copilot 中Skill 是一类自包含的文件夹内含一份SKILL.md指令文件并可捆绑代码模板、参考数据等资源参见 docs/README.skills.md。dotnet-timezone技能即由三部分组成skills/dotnet-timezone/SKILL.md技能主指令定义请求分流、解析流程、代码生成原则与响应格式skills/dotnet-timezone/references/timezone-index.md常用 Windows ↔ IANA 时区 ID 映射表与工具用法参考skills/dotnet-timezone/references/code-patterns.md七大可直接复制的 .NET 时区代码模式、常见错误对照表与决策指南。安装与使用方式Skills 按需加载遵循渐进式披露原则仅在执行相关任务时加载。可通过 GitHub CLI 安装需 GitHub CLI v2.90.0gh skills install github/awesome-copilot dotnet-timezone也可以将skills/dotnet-timezone文件夹手动复制到本地 skills 目录然后在提示词中引用或让 Agent 按需自动发现。第一步识别请求类型选对技术路线SKILL.md强调回答任何时区问题前先对请求进行分类地址或位置查询Address or location lookup时区 ID 查询Timezone ID lookupUTC / 本地时间转换UTC/local conversion跨平台时区兼容Cross-platform timezone compatibility调度或夏令时处理Scheduling or DST handlingAPI 或持久化设计API or persistence design在技术选型上技能给出的默认策略是若库的选择不明确跨平台场景默认使用TimeZoneConverter若涉及循环调度或严格 DST 规则优先使用NodaTime。这个默认策略与 references/code-patterns.md 末尾的决策指南一致TimeZoneInfo只适合 Windows-only 代码TimeZoneConverter适合大多数跨平台应用NodaTime用于 DST 算术或日历精度是核心诉求的场景DateTimeOffset用于 API 与序列化时间戳。解析地址与位置从地点到时区 ID 的完整流程当用户提供地址、城市、地区、国家或包含地名的文档时技能要求按以下步骤处理从输入中提取每一个位置查阅 references/timezone-index.md 获取常用 Windows 与 IANA 映射若精确位置未列出根据地理信息推断正确的 IANA 时区再映射为 Windows ID同时返回两种 ID 与可直接使用的 C# 示例。每个解析出的位置需要输出统一格式的信息块Location: resolved place Windows ID: windows id IANA ID: iana id UTC offset: standard offset and DST offset when relevant DST: yes/no随后附带一个跨平台代码片段例如将 UTC 转换为科伦坡斯里兰卡当地时间using TimeZoneConverter; TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Asia/Colombo); DateTime local TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz);如果输入包含多个位置则每个位置输出一个信息块再附一个组合了多时区的综合代码片段如果某个位置存在歧义可能命中多个时区则列出所有可能的时区匹配项交由用户选择确认。时区 ID 查询Windows 与 IANA 双格式约定TimeZoneInfo.FindSystemTimeZoneById()在不同平台上接受的 ID 格式不同这是 .NET 时区问题最常见的根源之一。技能要求始终同时给出两种格式Windows ID用于在 Windows 上调用TimeZoneInfo.FindSystemTimeZoneById()IANA ID用于 Linux、容器环境、NodaTime与TimeZoneConverter。Windows ↔ IANA 常用映射索引以下映射表完整摘自 references/timezone-index.md覆盖亚太、欧洲、美洲与非洲的常用时区UTC 偏移列中形如00:00/01:00表示标准时间/夏令时两个偏移。亚洲与太平洋Asia And PacificDisplay NameWindows IDIANA IDUTC OffsetDST?Sri Lanka Standard TimeSri Lanka Standard TimeAsia/Colombo05:30NoIndia Standard TimeIndia Standard TimeAsia/Calcutta05:30NoPakistan Standard TimePakistan Standard TimeAsia/Karachi05:00NoBangladesh Standard TimeBangladesh Standard TimeAsia/Dhaka06:00NoNepal Standard TimeNepal Standard TimeAsia/Katmandu05:45NoSE Asia Standard TimeSE Asia Standard TimeAsia/Bangkok07:00NoSingapore Standard TimeSingapore Standard TimeAsia/Singapore08:00NoChina Standard TimeChina Standard TimeAsia/Shanghai08:00NoTokyo Standard TimeTokyo Standard TimeAsia/Tokyo09:00NoKorea Standard TimeKorea Standard TimeAsia/Seoul09:00NoAUS Eastern Standard TimeAUS Eastern Standard TimeAustralia/Sydney10:00/11:00YesNew Zealand Standard TimeNew Zealand Standard TimePacific/Auckland12:00/13:00YesArabian Standard TimeArabian Standard TimeAsia/Dubai04:00NoArab Standard TimeArab Standard TimeAsia/Riyadh03:00NoIsrael Standard TimeIsrael Standard TimeAsia/Jerusalem02:00/03:00YesTurkey Standard TimeTurkey Standard TimeEurope/Istanbul03:00No欧洲EuropeDisplay NameWindows IDIANA IDUTC OffsetDST?UTCUTCEtc/UTC00:00NoGMT Standard TimeGMT Standard TimeEurope/London00:00/01:00YesW. Europe Standard TimeW. Europe Standard TimeEurope/Berlin01:00/02:00YesCentral Europe Standard TimeCentral Europe Standard TimeEurope/Budapest01:00/02:00YesRomance Standard TimeRomance Standard TimeEurope/Paris01:00/02:00YesE. Europe Standard TimeE. Europe Standard TimeAsia/Nicosia02:00/03:00YesGTB Standard TimeGTB Standard TimeEurope/Bucharest02:00/03:00YesRussian Standard TimeRussian Standard TimeEurope/Moscow03:00No美洲AmericasDisplay NameWindows IDIANA IDUTC OffsetDST?Eastern Standard TimeEastern Standard TimeAmerica/New_York-05:00/-04:00YesCentral Standard TimeCentral Standard TimeAmerica/Chicago-06:00/-05:00YesMountain Standard TimeMountain Standard TimeAmerica/Denver-07:00/-06:00YesPacific Standard TimePacific Standard TimeAmerica/Los_Angeles-08:00/-07:00YesAlaskan Standard TimeAlaskan Standard TimeAmerica/Anchorage-09:00/-08:00YesHawaiian Standard TimeHawaiian Standard TimePacific/Honolulu-10:00NoCanada Central Standard TimeCanada Central Standard TimeAmerica/Regina-06:00NoSA Eastern Standard TimeSA Eastern Standard TimeAmerica/Cayenne-03:00NoE. South America Standard TimeE. South America Standard TimeAmerica/Sao_Paulo-03:00/-02:00Yes非洲AfricaDisplay NameWindows IDIANA IDUTC OffsetDST?South Africa Standard TimeSouth Africa Standard TimeAfrica/Johannesburg02:00NoEgypt Standard TimeEgypt Standard TimeAfrica/Cairo02:00NoE. Africa Standard TimeE. Africa Standard TimeAfrica/Nairobi03:00NoW. Central Africa Standard TimeW. Central Africa Standard TimeAfrica/Lagos01:00NoMorocco Standard TimeMorocco Standard TimeAfrica/Casablanca00:00/01:00Yes程序化发现系统时区映射表无法覆盖全部时区实际开发中可用TimeZoneInfo.GetSystemTimeZones()枚举当前操作系统注册的全部时区及其显示名foreach (var tz in TimeZoneInfo.GetSystemTimeZones()) { Console.WriteLine($ID: {tz.Id} | Display: {tz.DisplayName}); }注意该枚举返回的是当前运行平台的时区 IDWindows 上为 Windows IDLinux 上为 IANA ID这正是跨平台代码必须通过TimeZoneConverter或NodaTime屏蔽差异的原因。生成代码七大可复制模式与选用原则技能要求从 references/code-patterns.md 中选取满足需求的最小模式。七个模式的定位如下模式适用场景Pattern 1TimeZoneInfo仅限 Windows-only 代码Pattern 2TimeZoneConverter跨平台转换Pattern 3NodaTime严格时区运算与 DST 敏感调度Pattern 4DateTimeOffsetAPI 与数据传输Pattern 5ASP.NET Core 持久化与展示Pattern 6循环任务与调度器Pattern 7歧义与无效 DST 时间戳推荐第三方库时需同时给出包引用说明。以下逐一展开。Pattern 1基础 TimeZoneInfo仅 Windows仅当应用只运行在 Windows 且接受 Windows 时区 ID 时使用DateTime utcNow DateTime.UtcNow; TimeZoneInfo sriLankaTz TimeZoneInfo.FindSystemTimeZoneById(Sri Lanka Standard Time); DateTime localTime TimeZoneInfo.ConvertTimeFromUtc(utcNow, sriLankaTz); DateTime backToUtc TimeZoneInfo.ConvertTimeToUtc(localTime, sriLankaTz); TimeZoneInfo tokyoTz TimeZoneInfo.FindSystemTimeZoneById(Tokyo Standard Time); DateTime tokyoTime TimeZoneInfo.ConvertTime(localTime, sriLankaTz, tokyoTz);这段代码演示了三个基础操作UTC 转本地、本地回 UTC、以及两个时区之间直接转换以ConvertTime在任意两个TimeZoneInfo间换算。Linux、容器或混合环境应改用TimeZoneConverter或NodaTime——因为在 Linux 上FindSystemTimeZoneById(Sri Lanka Standard Time)无法识别该 Windows ID。Pattern 2TimeZoneConverter 跨平台方案推荐默认这是大多数同时运行于 Windows 与 Linux 的 .NET 应用的推荐默认方案。包引用PackageReference IncludeTimeZoneConverter Version6.* /核心用法——使用 IANA ID 获取TimeZoneInfousing TimeZoneConverter; TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Asia/Colombo); DateTime converted TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz);TZConvert.GetTimeZoneInfo()同样接受 Windows ID实现双向兼容TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Sri Lanka Standard Time);此外references/timezone-index.md 还提供了显式的双向转换 API便于在两种 ID 之间切换string ianaId TZConvert.WindowsToIana(Sri Lanka Standard Time); string windowsId TZConvert.IanaToWindows(Asia/Colombo); TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Asia/Colombo);Pattern 3NodaTime 严格时区运算当严格时区算术、循环调度或 DST 边界场景要求正确性优先于依赖数量时使用。包引用PackageReference IncludeNodaTime Version3.* /跨时区换算科伦坡 → 东京与本地时间构造示例using NodaTime; DateTimeZone colomboZone DateTimeZoneProviders.Tzdb[Asia/Colombo]; Instant now SystemClock.Instance.GetCurrentInstant(); ZonedDateTime colomboTime now.InZone(colomboZone); DateTimeZone tokyoZone DateTimeZoneProviders.Tzdb[Asia/Tokyo]; ZonedDateTime tokyoTime colomboTime.WithZone(tokyoZone); LocalDateTime localDt new LocalDateTime(2024, 6, 15, 14, 30, 0); ZonedDateTime zoned colomboZone.AtStrictly(localDt); Instant utcInstant zoned.ToInstant();这里Instant是 NodaTime 对 UTC 时刻的建模ZonedDateTime携带完整时区与偏移信息AtStrictly对歧义或无效的本地时间会直接抛出异常区别于宽松模式从而在 DST 边界上强制显式决策。Pattern 4DateTimeOffset 用于 API 边界跨越服务或进程边界传输的时间值应优先使用DateTimeOffset它同时携带 UTC 时刻与偏移杜绝裸DateTime无法表达时刻的歧义using TimeZoneConverter; DateTimeOffset utcNow DateTimeOffset.UtcNow; TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Asia/Colombo); DateTimeOffset colomboTime TimeZoneInfo.ConvertTime(utcNow, tz);Pattern 5ASP.NET Core 持久化与展示核心原则存储 UTC在边界处转换Store UTC, convert at the edges。写入时存 UTC读取后按用户时区转换为展示用时间using TimeZoneConverter; entity.CreatedAtUtc DateTime.UtcNow; public DateTimeOffset ToUserTime(DateTime utc, string userIanaTimezone) { var tz TZConvert.GetTimeZoneInfo(userIanaTimezone); return TimeZoneInfo.ConvertTimeFromUtc(utc, tz); }注意这里入参userIanaTimezone是用户配置的 IANA ID如Asia/Shanghai通过TZConvert转换为运行平台可识别的TimeZoneInfo这正是跨平台持久化层的关键接缝。Pattern 6调度与循环任务在调度之前先把用户可见的本地时间换算为 UTC结合 Hangfire 时把用户时区直接配置进RecurringJobOptions让调度器按用户时区解释 CRON 表达式using TimeZoneConverter; TimeZoneInfo tz TZConvert.GetTimeZoneInfo(Asia/Colombo); DateTime scheduledLocal new DateTime(2024, 12, 1, 9, 0, 0, DateTimeKind.Unspecified); DateTime scheduledUtc TimeZoneInfo.ConvertTimeToUtc(scheduledLocal, tz);RecurringJob.AddOrUpdate( morning-job, () DoWork(), 0 9 * * *, new RecurringJobOptions { TimeZone tz });DateTimeKind.Unspecified在此是有意为之它表示这是某时区下的墙上时间随后通过ConvertTimeToUtc结合明确时区解释为 UTC这正是技能中除非是有意的输入否则将DateTimeKind.Unspecified视为 bug 风险这句话的正确应用场景。Pattern 7DST 歧义与无效时间实施夏令时的时区会存在两类边界时间被重复的时间回拨时同一墙钟时间出现两次与被跳过的时间前拨时墙钟时间不存在。使用IsAmbiguousTime与IsInvalidTime显式处理using TimeZoneConverter; TimeZoneInfo tz TZConvert.GetTimeZoneInfo(America/New_York); DateTime localTime new DateTime(2024, 11, 3, 1, 30, 0); if (tz.IsAmbiguousTime(localTime)) { var offsets tz.GetAmbiguousTimeOffsets(localTime); var standardOffset offsets.Min(); var dto new DateTimeOffset(localTime, standardOffset); } if (tz.IsInvalidTime(localTime)) { localTime localTime.AddHours(1); }针对歧义时间GetAmbiguousTimeOffsets返回两个可能的偏移示例选择其中较小的标准时间偏移构造DateTimeOffset——这是业务上的显式取舍不同场景可能需要不同策略针对无效时间示例采用向后推 1 小时的简单修正策略。真实业务中应把这两种决策显式记录进需求与文档。常见陷阱清单正确 vs 错误对照references/code-patterns.md 提供了一张可直接对照的常见错误表WrongBetterDateTime.Nowin server codeDateTime.UtcNowStoring local timestamps in the databaseStore UTC and convert for displayHardcoding offsets such as05:30Use timezone IDsUsingFindSystemTimeZoneById(Asia/Colombo)on WindowsUseTZConvert.GetTimeZoneInfo(Asia/Colombo)Comparing localDateTimevalues from different zonesCompare UTC or useDateTimeOffsetCreatingDateTimewithout intentional kind semanticsUseUtc,Local, or deliberateUnspecified与 SKILL.md 中的警告清单互为印证需要在相关场景中主动提示TimeZoneInfo.FindSystemTimeZoneById()对时区 ID 是平台相关的Windows 只认 Windows IDLinux 只认 IANA ID不要在数据库中存储DateTime.Now应存储 UTC除非是有意为之的输入否则将DateTimeKind.Unspecified视为 bug 风险DST 转换可能跳过或重复本地时间Azure Windows 与 Azure Linux 环境可能期望不同的时区 ID 格式——同一份部署清单在两个平台上需要不同的时区配置。响应结构简洁、代码优先技能对回复格式做了明确约定以保证输出可读、可直接落地地址/位置类请求为每个位置返回解析出的时区信息块用一句话给出推荐的实现方案附带可复制粘贴的 C# 片段。代码/架构类请求用一句话说明推荐方案如相关给出时区 IDWindows IANA 双格式提供最小可用代码片段如需要说明 NuGet 包要求如有必要附加一条相关陷阱警告。整体原则是保持响应简洁、代码优先Keep responses concise and code-first。决策指南与原理小结综合 references/code-patterns.md 的决策指南选型可以收敛为四句话TimeZoneInfo仅用于 Windows-only 代码使用 Windows IDTimeZoneConverter用于大多数跨平台应用Windows/Linux/容器混合部署NodaTime当 DST 算术或日历精度是核心诉求时使用如严格调度、边界时间强制决策DateTimeOffset用于 API 与序列化时间戳跨服务、跨进程传值。从仓库源码结构看该技能通过主指令SKILL.md 映射参考timezone-index.md 代码模式code-patterns.md的分层设计实现了渐进式披露Agent 先按SKILL.md判断请求类型并分流需要映射数据时查timezone-index.md需要代码骨架时从code-patterns.md取最小可用模式。这种先判型、再查表、后取码的工作流本身就是一个可复用的技术咨询范式——无论你是人还是 Agent处理任何 .NET 时区问题都可以先回答四个问题运行平台是什么时间值在哪个边界传递是否涉及 DST 边界是否需要循环调度答案一旦明确正确的 API 与模式组合就自然浮现了。【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考