将UTC日期时间转换为另一个时区

52

我有一个从数据库记录中获取的UTC DateTime值。我还有一个用户指定的时区(一个TimeZoneInfo实例)。如何将该UTC DateTime转换为用户所在的本地时区?另外,如何确定用户指定的时区当前是否正在观察夏令时?我正在使用.NET 3.5。

谢谢, 马克

6个回答

64

最好的方法是直接使用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实例的成员而不是静态函数,我就不用来StackOverflow上找答案了。 - MarkPflug

26

如果您想将一个DateTimeOffset转换成另一个DateTimeOffset,可以在TimeZoneInfo中使用专用函数:

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

22
看一下DateTimeOffset结构:
// user-specified time zone
TimeZoneInfo southPole =
    TimeZoneInfo.FindSystemTimeZoneById("Antarctica/South Pole Standard Time");

// a 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);

有关夏令时,请参考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"); - Mark Richman
10
这段代码无法编译。该时区ID不存在,如果替换为有效的ID,则会出现“UTC DateTime实例的UTC偏移必须为0”的错误。 - The Muffin Man
为避免在 dateAndOffset 中出现错误,请选择 DateTime cstTime = utcTime.AddTicks(southPole.BaseUtcOffset.Ticks); - Saneesh kunjunni

13

南极洲答案仅适用于与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");

19
static public?异端邪说,烧掉女巫。 - Chris Marisic

2
这里还有一个需要注意的地方:如果你在Linux服务器上运行代码,需要使用Linux系统中的时区名称。例如,“Central Standard Time”应该是“America/Chicago”。时区列表在这里: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;
    }
}

1
       //  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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接