将 UTC DateTime 转换为另一个时区

Posted

技术标签:

【中文标题】将 UTC DateTime 转换为另一个时区【英文标题】:Convert UTC DateTime to another Time Zone 【发布时间】:2011-02-02 15:26:46 【问题描述】:

我有一个来自数据库记录的 UTC 日期时间值。我还有一个用户指定的时区(TimeZoneInfo 的一个实例)。如何将该 UTC DateTime 转换为用户的本地时区?另外,如何确定用户指定的时区当前是否正在遵守 DST?我正在使用 .NET 3.5。

谢谢, 标记

【问题讨论】:

【参考方案1】:

最好的方法就是使用TimeZoneInfo.ConvertTimeFromUtc

// you said you had these already
DateTime utc = new DateTime(2014, 6, 4, 12, 34, 0);
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

// it's a simple one-liner
DateTime pacific = TimeZoneInfo.ConvertTimeFromUtc(utc, tzi);

唯一的问题是传入的DateTime 值可能没有DateTimeKind.Local 类型。它必须是 UtcUnspecified

【讨论】:

呃,如果他们只是让 Convert 函数成为 tzi 实例的成员而不是静态的,我就不必来 *** 来解决这个问题了。【参考方案2】:

如果要将 DateTimeOffset 转换为另一个 DateTimeOffset,可以使用 TimeZoneInfo 中的专用函数:

DateTimeOffset newTime = TimeZoneInfo.ConvertTime(
    DateTimeOffset.UtcNow, 
    TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
);

【讨论】:

【参考方案3】:

看看DateTimeOffset 结构:

// user-specified time zone
TimeZoneInfo southPole =
    TimeZoneInfo.FindSystemTimeZoneById("Antarctica/South Pole Standard Time");

// an UTC DateTime
DateTime utcTime = new DateTime(2007, 07, 12, 06, 32, 00, DateTimeKind.Utc);

// DateTime with offset
DateTimeOffset dateAndOffset =
    new DateTimeOffset(utcTime, southPole.GetUtcOffset(utcTime));

Console.WriteLine(dateAndOffset);

对于 DST,请参阅 TimeZoneInfo.IsDaylightSavingTime 方法。

bool isDst = southpole.IsDaylightSavingTime(DateTime.UtcNow);

【讨论】:

我必须多走一步才能得到我的当地时间: var offset = tzi.GetUtcOffset(utcTime); var siteLocalTime = utcTime.Add(offset); return siteLocalTime.ToString("MM/dd/yyyy HH:mm"); 此代码无法编译。该时区 ID 不存在,如果将其替换为有效的 ID,则会收到有关 The UTC Offset for Utc DateTime instances must be 0 的错误。 为避免 dateAndOffset 出错选择 DateTime cstTime = utcTime.AddTicks(southPole.BaseUtcOffset.Ticks);【参考方案4】:

南极洲的答案仅适用于与 UTC 匹配的时区。我对这个DateTimeOffset 函数感到非常痛苦,经过数小时的反复试验,我设法生成了一个适用于所有时区的实用转换扩展函数。

static public class DateTimeFunctions

    static public DateTimeOffset ConvertUtcTimeToTimeZone(this DateTime dateTime, string toTimeZoneDesc)
    
        if (dateTime.Kind != DateTimeKind.Utc) throw new Exception("dateTime needs to have Kind property set to Utc");
        var toUtcOffset = TimeZoneInfo.FindSystemTimeZoneById(toTimeZoneDesc).GetUtcOffset(dateTime);
        var convertedTime = DateTime.SpecifyKind(dateTime.Add(toUtcOffset), DateTimeKind.Unspecified);
        return new DateTimeOffset(convertedTime, toUtcOffset);
    

例子:

var currentTimeInPacificTime = DateTime.UtcNow.ConvertUtcTimeToTimeZone("Pacific Standard Time");

【讨论】:

static public?异端,烧死女巫【参考方案5】:
       //  TO get Currrent Time in current Time Zone of your System

        var dt = DateTime.Now;

        Console.WriteLine(dt);

        // Display Time Zone of your System

        Console.WriteLine(TimeZoneInfo.Local);

        // Convert Current Date Time to UTC Date Time

        var utc = TimeZoneInfo.ConvertTimeToUtc(dt, TimeZoneInfo.Local);

        Console.WriteLine(utc);

        // Convert UTC Time to Current Time Zone

        DateTime pacific = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);

        Console.WriteLine(pacific);

        Console.ReadLine();

【讨论】:

【参考方案6】:

还有一个问题:如果您在 Linux 服务器上运行代码,则需要使用 Linux 系统来命名时区。例如,“Central Standard Time”将是“America/Chicago”。 tz 列表在这里:https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

这是一个使用 isWindows 开关的示例:

public static class DateTimeHelper

    public static string ConvertUtcToCst(this string dateTimeString)
    
        if (string.IsNullOrWhiteSpace(dateTimeString))
        
            return string.Empty;
        

        if (DateTime.TryParse(dateTimeString, out DateTime outputDateTime))
        
            try
            
                var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
                TimeZoneInfo cstZone = null;
                if (isWindows)
                
                    cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
                
                else
                
                    cstZone = TimeZoneInfo.FindSystemTimeZoneById("America/Chicago");
                

                var cstDateTime = TimeZoneInfo.ConvertTimeFromUtc(outputDateTime, cstZone);
                return cstDateTime.ToString();
            
            catch (TimeZoneNotFoundException)
            
                return "The registry does not define the Central Standard Time zone.";
            
            catch (InvalidTimeZoneException)
            
                return "Registry data on the Central Standard Time zone has been corrupted.";
            
            catch (Exception ex)
            
                return $"Error :: ex.Message :: ex.ToString()";
            
        

        return string.Empty;
    

【讨论】:

以上是关于将 UTC DateTime 转换为另一个时区的主要内容,如果未能解决你的问题,请参考以下文章

将 Postgres 中没有时区的 DateTime 字段从中欧时间转换为 UTC

如何将MySQL Datetime UTC转换为实际时区

如何将 UTC DateTimeOffset 转换为使用系统时区的 DateTime

Python:如何将日期时间/时间戳从一个时区转换为另一个时区?

将 UTC 日期转换为其他时区

C#与mongodb DateTime转换时区相差8小时