将当前本地时间转换为任何其他时区

时间:2016-10-21 11:12:22

标签: c# .net datetime

我想通过将本地时间与UTC进行比较来测试一些与时区相关的代码。然而,这个测试依赖于当地时间与UTC不同而且我在英国这样的一年中有6个月,根据DateTime比较测试,当地时间是UTC(由于夏季时间)。

我可以对我的测试进行硬编码,将UTCNow转换为某个时区,例如EST,但是我的代码在美国系统中使用的机会很少,现在我遇到了同样的问题。

那么有没有一种方法可以轻松地将DateTime.UtcNow转换为与我的本地时区明确不同的时区,而无需对其进行硬编码或假设我所在的时区?

3 个答案:

答案 0 :(得分:2)

好的,正如我在评论中所做的那样,如果你想获得与你的时区不同的时区,你可以这样做:

var zone = TimeZoneInfo.GetSystemTimeZones()
           .Where(x=>x.BaseUtcOffset != TimeZoneInfo.Local.BaseUtcOffset)
           .First();

要将UTC DateTime转换为其他时区,您必须使用TimeZoneInfo.ConvertTimeFromUtc,示例:

var datetime = // datetime in UTC, for example, DateTime.UtcNow
var zone = // target zone
return TimeZoneInfo.ConvertTimeFromUtc(datetime, zone);

您可以检查我的宠物项目中的样本here

答案 1 :(得分:1)

.net中的时区是一个非常混乱的问题。 DateTime实际上只支持本地和UTC时区,它没有不同区域的概念,因为它只获取机器的当前偏移量并将其应用于UTC中的滴答计数值。

所以在第一时间没有办法改变到另一个时区,但你可以模拟一些东西。如果您希望每个示例模拟时区GMT + 2,则必须首先检索当前区域偏移量,并将此偏移量和所需偏移量的差值添加到本地日期,如下所示:

TimeSpan targetOffset = new TimeSpan(2, 0, 0) - TimeZoneInfo.Local.BaseUtcOffset; //target to GMT+2
DateTime targetNow = DateTime.Now + targetOffset;

通过这种方式,Date将具有类似于该时区的值,但是对于使用datetime对象而不仅仅是年/月/日/小时/分钟/秒的计算,所有这些都将是错误的对象将被标记为本地,因此将具有错误的值。

要解决此问题,您有两个选择,即反转您的逻辑(将非本地时间转换为本地时间)或仅使用UTC日期。

第一种方法很简单:

DateTime nonLocal = new DateTime(2016, 10, 21, 13, 33, 0); //We suppose we want 2016-10-21 13:33:00 at GMT+2
DateTime local = nonLocal + (TimeZoneInfo.Local.BaseUtcOffset - new TimeSpan(2, 0, 0));

这将产生正确的DateTime操作,但是,在这里我们再次遇到问题,如果你使用年/月/日/小时/分钟它们将在你的本地区域,而不是在假定的区域和代码中使用这些属性将失败。

最后,最好的方法是第二个,你只是忘记了时区,每当你得到一个DateTime你将它转换为UTC时,所有都将工作,当你需要代表数据时只需将它转换为本地,所有是完成后,无需担心DateTime算法或属性不同仅仅是因为它们位于另一个时区。

答案 2 :(得分:-1)

 public static class DateTimeExtensions
    {
        public static DateTime As(this DateTime source, string timeZoneName)
        {
            DateTime utcTime = DateTime.SpecifyKind(source, DateTimeKind.Unspecified);
            TimeZoneInfo newTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
            return TimeZoneInfo.ConvertTimeFromUtc(utcTime, newTimeZone);
        }
    }

用法:

        DateTime date1 = DateTime.UtcNow;
        DateTime date2 = date1.As("Eastern Standard Time");