如何在指定时区创建指定日期的固定时间点DateTime对象
Great question! When you need to generate a DateTime object for a fixed time (like 9 AM) on 2018-04-23 in a specific time zone, relying on manual offset adjustments (like AddHours) is risky—it won’t account for daylight saving time (DST) or other time zone rule changes. Instead, use the TimeZoneInfo class for reliable, rule-aware conversions.
Step-by-Step Solution
1. Get the Target Time Zone Object
First, you need the system ID for your target time zone. You can list all available IDs with TimeZoneInfo.GetSystemTimeZones(), but common examples include:
"Tokyo Standard Time"(UTC+9, no DST)"Eastern Standard Time"(US Eastern, UTC-5/UTC-4 with DST)"Central European Standard Time"(UTC+1/UTC+2 with DST)
Use FindSystemTimeZoneById to retrieve the zone:
TimeZoneInfo targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
2. Create a Base DateTime for the Target Local Time
Construct a DateTime representing the desired local time in the target zone, marking it as Unspecified (since we haven’t tied it to a zone yet):
DateTime targetLocalTime = new DateTime(2018, 4, 23, 9, 0, 0, DateTimeKind.Unspecified);
3. Convert to the Target Time Zone
Use TimeZoneInfo.ConvertTime to apply the time zone rules and get the final DateTime. This method automatically handles DST and other adjustments:
DateTime finalDateTime = TimeZoneInfo.ConvertTime(targetLocalTime, targetTimeZone);
Alternative: Convert from UTC
If you prefer starting with a UTC time (which avoids ambiguity), calculate the UTC equivalent of your target time and convert it to the zone:
// UTC time equivalent to 9 AM Tokyo on 2018-04-23 is 00:00 UTC DateTime utcTime = new DateTime(2018, 4, 23, 0, 0, 0, DateTimeKind.Utc); TimeZoneInfo targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); DateTime finalDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime, targetTimeZone);
Important Notes
- Avoid Manual Offsets: Using
AddHours(9)works for fixed-offset zones like Tokyo, but fails for zones with DST (e.g., US Eastern switches between UTC-5 and UTC-4).TimeZoneInfohandles these edge cases automatically. - DateTime vs. DateTimeOffset: The
DateTimetype doesn’t explicitly store time zone info (itsKindproperty only indicates Local/Utc/Unspecified). For clearer, unambiguous time handling, consider usingDateTimeOffsetinstead:TimeZoneInfo targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); DateTimeOffset targetDateTimeOffset = new DateTimeOffset(2018, 4, 23, 9, 0, 0, targetTimeZone.GetUtcOffset(new DateTime(2018, 4, 23)));
内容的提问来源于stack exchange,提问作者Luiso

