C#中将UTC时间转换为本地时间

8

我希望展示一个事件的日期和时间,该事件将根据用户的时区进行管理。为了检查时区,我将我的系统时区更改为另一个时区,但我的代码仍然获取本地时区。 以下是我的代码:

我正在使用Cassendra数据库和C# .NET MVC。

DateTime startTimeFormate = x.Startdate;
DateTime endTimeFormate = x.Enddate;
TimeZone zone = TimeZone.CurrentTimeZone;
DateTime startTime = zone.ToLocalTime(startTimeFormate);
DateTime endTime = zone.ToLocalTime(endTimeFormate);

可能是如何在C#中获取当前用户时区的重复问题。 - ArunPratap
如果您关心时区,请至少使用DateTimeOffset而不是DateTime。至于您的问题,x.StartDatex.EndDateDateTimeKind值是什么?本地时间、UTC还是未指定?只有在想要将UTC转换为本地时间时,ToLocalTime才有意义。在其他情况下,唯一合乎逻辑的结果是返回具有“Local” DateTimeKind的相同日期时间值。 - Panagiotis Kanavos
如果值来自数据库,它们可能是未指定的,因为数据库提供程序不知道它们代表哪种日期或使用哪个偏移量。 - Panagiotis Kanavos
最后,要将DateTime值从一个时区转换为另一个时区,请使用TimezoneInfo.ConvertTime - Panagiotis Kanavos
4个回答

12

要将 UTC DateTime 转换为您的 Local DateTime,您需要使用如下的 TimeZoneInfo

DateTime startTimeFormate = x.Startdate; // This  is utc date time
TimeZoneInfo systemTimeZone = TimeZoneInfo.Local;
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(startTimeFormate, systemTimeZone);

此外,如果您想将{{UTC DateTime}}转换为用户特定的{{Local DateTime}},请按照以下步骤操作:
string userTimeZoneId = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneId);
DateTime userLocalDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, userTimeZoneId);

注意:在.NET中,TimeZone现已过时,已被弃用。请改用TimeZoneInfo

2

TimeZone.CurrentTimeZoneTimeZoneInfo.LocalToLocalTime使用服务器的本地时区,而不是最终用户的时区。

相反,首先查看如何在您的.NET代码中可靠地获取最终用户的时区

然后,假设您现在拥有一个TimeZoneInfo对象,只需使用TimeZoneInfo.ConvertTimeFromUtc方法即可。


1
这些是我使用的DateTime助手,涵盖了我迄今为止所需的所有情况。
public static class DateTimeHelpers
  {
    public static DateTime ConvertToUTC(DateTime dateTimeToConvert, string sourceZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById(sourceZoneIdentifier);
      TimeZoneInfo destinationTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");

      return TimeZoneInfo.ConvertTime(dateTimeToConvert, sourceTZ, destinationTZ);
    }

    public static DateTime ConvertToTimezone(DateTime utcDateTime, string destinationZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");
      TimeZoneInfo destinazionTZ = TimeZoneInfo.FindSystemTimeZoneById(destinationZoneIdentifier);

      return DateTime.SpecifyKind(TimeZoneInfo.ConvertTime(utcDateTime, sourceTZ, destinazionTZ), DateTimeKind.Local);
    }

    public static DateTime GetCurrentDateTimeInZone(string destinationZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");
      TimeZoneInfo destinazionTZ = TimeZoneInfo.FindSystemTimeZoneById(destinationZoneIdentifier);

      return DateTime.SpecifyKind(TimeZoneInfo.ConvertTime(DateTime.UtcNow, sourceTZ, destinazionTZ), DateTimeKind.Local);
    }
  }

0
根据MSDN TimeZone.CurrentTimeZone 属性文档,本地时区在第一次调用 TimeZone.CurrentTimeZone 后会被缓存。实际上,这意味着只要不支持运行时动态更新时区,您的代码应该可以正常运行。为了立即看到更改,在调用 TimeZone.CurrentTimeZone 之前,您应该调用
TimeZoneInfo.ClearCachedData();

这在MSDN文章中有详细说明:

调用者注意事项

本地时区数据在首次使用CurrentTimeZone检索时区信息后被缓存。如果系统的本地时区随后发生更改,则CurrentTimeZone属性不会反映此更改。如果您需要在应用程序运行时处理时区更改,请使用TimeZoneInfo类并调用其ClearCachedData()方法。


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