如何在特定时区转换 DateTime?

Posted

技术标签:

【中文标题】如何在特定时区转换 DateTime?【英文标题】:How to convert DateTime in Specific timezone? 【发布时间】:2018-11-24 09:40:22 【问题描述】:

我很难理解 UTC 的工作原理。

我必须执行以下操作,但如果我能得到正确的结果,我仍然感到困惑。

目标:

    确保数据库中所有保存的日期均为 UTC 格式 更新 DefaultTimezone 为马尼拉时间 确保所有返回的日期都在马尼拉时间

所以代码是:

public ConvertDate(DateTime? dateTime)

    if (dateTime != null)
    
        Value = (DateTime)dateTime;
        TimeZone = GetFromConfig.DefaultTimeZone(); 
    



public ConvertDate(DateTime? dateTime, int GMTTimeZone)

    if (dateTime != null)
    
        Value = (DateTime)dateTime;
        TimeZone = GMTTimeZone;
    



public int TimeZone

    get  return m_TimeZone; 
    set  m_TimeZone = value; 



DateTime m_Value;
public DateTime Value

    get  return m_Value; 
    set 
     
        m_Value = value;
        DateTime converted = m_Value.ToUniversalTime().ToLocalTime();
    

示例用法:

DateTime SampleInputFromUser = new DateTime(2012, 1, 22);
ConvertDate newConversion = new ConvertDate(SampleInputFromUser, 21);
DateTime answer = newConversion.Value;

现在我对“时区”感到困惑。我不知道如何使用它来获得目标。 希望您理解我的问题并有想法完成目标。

编辑

根据@raveturned 的回答,我得到以下代码:

***在 ConvertDate 方法中添加

TimeZoneInfo timeInfo = TimeZoneInfo.FindSystemTimeZoneById(GetFromConfig.ManilaTimeZoneKey());
ManilaTime = TimeZoneInfo.ConvertTime(dateTime.Value, TimeZoneInfo.Local, timeInfo).ToUniversalTime();

**新属性

DateTime _ManilaTime;
public DateTime ManilaTime

    get  return _ManilaTime; 
    set  _ManilaTime = value; 

【问题讨论】:

***.com/questions/246498/…的可能重复 【参考方案1】:

.NET 框架已经具有可用于在不同时区之间转换 DateTime 的类和方法。看看 TimeZoneInfo 类的 ConvertTime 方法。

编辑:当您有时间放入数据库时​​,假设它是使用正确的时区信息创建的,您可以轻松转换为 UTC:

DateTime utcTime = inputDateTime.ToUniversalTime();

在问题编辑中获取 timeInfo:

TimeZoneInfo timeInfo = TimeZoneInfo.FindSystemTimeZoneById(GetFromConfig.ManilaTimeZoneKey());

当您将数据库时间发送给用户时,使用timeInfo 将其转换为正确的时区。

DateTime userTime = TimeZoneInfo.ConvertTimeFromUtc(dbDateTime, timeInfo);

我个人会尝试将此逻辑与属性 get/set 方法分开。

【讨论】:

这个list of timezone IDs 可能会有所帮助【参考方案2】:
var date = System.TimeZoneInfo.ConvertTimeFromUtc(
    DateTime.UtcNow, 
    TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));

【讨论】:

虽然这段代码可以回答作者的问题,但它缺乏解释。原始的 sn-ps 没有帮助。查看帮助页面了解更多关于how to write a good answer的信息。【参考方案3】:
TimeZoneInfo infotime = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time (Mexico)");
DateTime thisDate = TimeZoneInfo.ConvertTimeFromUtc(datetimeFromBD, infotime);

【讨论】:

【参考方案4】:

帮助他人:

    static void ChangeTimezone()
    
        // Timezone string here:
        foreach (TimeZoneInfo z in TimeZoneInfo.GetSystemTimeZones())
            Console.WriteLine(z.Id);

        // Use one of those timezone strings
        DateTime localDt = DateTime.Today;
        DateTime utcTime = localDt.ToUniversalTime();
        TimeZoneInfo timeInfo = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
        DateTime estDt = TimeZoneInfo.ConvertTimeFromUtc(utcTime, timeInfo);
        return;
    

【讨论】:

【参考方案5】:

对于在跨平台获取 TimeZoneInfo(Windows 和 Linux 之间的时区 ID 不同)时遇到问题的任何人,.NET 6 解决了这个问题:

从此版本开始,如果在系统上找不到请求的时区,TimeZoneInfo.FindSystemTimeZoneById 方法将自动将其输入转换为相反的格式。这意味着您现在可以在任何安装了时区数据的操作系统上使用 IANA 或 Windows 时区 ID*。它使用相同的 CLDR 映射,但通过 .NET 的 ICU 全球化支持获取它们,因此您不必使用单独的库。

一个简单的例子:

// Both of these will now work on any supported OS where ICU and time zone data are available.
TimeZoneInfo tzi1 = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
TimeZoneInfo tzi2 = TimeZoneInfo.FindSystemTimeZoneById("Australia/Sydney");

了解更多信息here

正如其他答案中所述:要从 UTC 获取所需时区的 DateTime,请使用 TimeZoneInfo.ConvertTimeFromUtc(DateTime, TimeZoneInfo) Method

【讨论】:

以上是关于如何在特定时区转换 DateTime?的主要内容,如果未能解决你的问题,请参考以下文章

如何将日期时间(在特定时区)转换为纪元秒

如何在不同的系统文化中转换 DateTime?

如何在特定时区(最好是我的应用程序的默认时区,而不是 UTC)中创建新的 DateTime 对象?

如何在 Pandas 中转换 datetime 列的时区?

如何将 Long 类型的 datetime 转换为具有正确时区的 DateTime

如何从 MySQL DATETIME 转换为 java.time.Instant 并在系统默认时区显示给用户?