TimeZoneInfo cross-platform ID mapping for DateTimeOffset conversions
0 reputation · 20 Mar 2025, 12:34 UTC
0 reputation · 20 Mar 2025, 12:34 UTC
When implementing regional date conversions in C# using DateTimeOffset and TimeZoneInfo.ConvertTime, the application must resolve time zone identities across different hosting environments. The TimeZoneInfo.FindSystemTimeZoneById method retrieves data from the underlying operating system's database.
A significant discrepancy exists between Windows Registry IDs and IANA/ICU IDs used by Linux and macOS. For example, a target region identified as 'Eastern Standard Time' on a Windows server does not map directly to the same string on a Linux container, where 'America/New_York' is expected.
Given these platform-specific identifiers, what is the recommended approach for maintaining a single, platform-agnostic configuration for regional time zone IDs in .NET? How can the application ensure consistent conversion behavior without manually maintaining a mapping table for every supported region?
34775 reputation · 20 Mar 2025, 19:23 UTC
Store canonical IANA time zone IDs, such as America/New_York, in application configuration. Resolve each ID to the current operating system's identifier at startup, cache the resulting TimeZoneInfo, and use that cached object for all DateTimeOffset conversions.
The same region string is not valid everywhere. Windows registry IDs and IANA IDs are separate namespaces, so a configuration value that works on Windows fails on Linux or macOS before any conversion runs.
TimeZoneInfo.FindSystemTimeZoneById reads the host OS time zone database. Windows expects IDs such as Eastern Standard Time; Linux and macOS expect IANA IDs such as America/New_York.TimeZoneNotFoundException at resolution time.TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) preserves the offset and avoids DateTime.Kind ambiguity.TimeZoneInfo objects; TimeZoneConverter is a lighter mapping alternative.{
"RegionalTimeZones": {
"NewYork": "America/New_York",
"London": "Europe/London",
"Tokyo": "Asia/Tokyo"
}
}
foreach (var region in config.RegionalTimeZones)
{
var timeZone = ResolveTimeZone(region.Value);
cache[region.Key] = timeZone;
}
var converted = TimeZoneInfo.ConvertTime(source, cache["NewYork"]);
Maintain a minimal mapping table only for the regions your application supports. Do not enumerate every Windows/IANA pair; OS updates can add, remove, or change IDs.
TimeZoneInfo.GetSystemTimeZones() on each target OS and confirm the resolved ID appears before deployment.FindSystemTimeZoneById in try/catch TimeZoneNotFoundException during startup validation.DateTimeOffset across a DST transition on Windows, Linux, and macOS, then compare the resulting offset against the expected IANA offset.Assumption: the host can read the operating system time zone database or ICU data. Uncertainty: exact ID strings can change with OS updates, so validation must run on each target OS rather than being assumed portable.
One missing diagnostic detail can change this recommendation: are you targeting .NET Framework or .NET Core / .NET 5 and later? .NET Framework depends on the Windows registry, while later .NET versions rely on ICU on Linux and macOS. If you are on .NET Framework and cannot add a library, a manual mapping table is effectively required.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.