在 Azure Web 应用程序上更改时区不适用于 DateTimeOffset.Now?

Posted

技术标签:

【中文标题】在 Azure Web 应用程序上更改时区不适用于 DateTimeOffset.Now?【英文标题】:Changing TimeZone on Azure Web Apps Doesn't work for DateTimeOffset.Now? 【发布时间】:2015-09-05 13:05:57 【问题描述】:

Accordingtomultiplepostings,Microsoft 启用了使用应用程序设置 - WEBSITE_TIME_ZONE - 来控制 Web 服务器的时区的能力。

为此,我将此值设置为“东部标准时间”,这是我的本地时区。

在 ASP.NET MVC Razor 页面上,我添加了以下代码:

DateTime.Now: @DateTime.Now
DateTimeOffset.Now: @DateTimeOffset.Now
DateTime.UtcNow: @DateTimeOffset.UtcNow

当我昨晚在东部标准时间下午 5:10:07 运行时,它给出了以下输出:

DateTime.Now: 6/18/2015 5:10:07 PM
DateTimeOffset.Now: 6/18/2015 5:10:07 PM +00:00
DateTime.UtcNow: 6/18/2015 9:10:07 PM

如您所见,设置正确地允许DateTime.Now 在我的时区返回正确的值,而不是像 Azure 网站/Web 应用程序通常那样返回 UTC。 DateTime.UtcNow 总是返回正确的值,原因很明显。

但是,DateTimeOffset.Now 返回本地时间,但偏移量为+00:00 - 几乎就像更改了时钟而不是时区一样。即使documentation 说(强调我的),也会发生这种情况:

获取一个 DateTimeOffset 对象,该对象设置为当前计算机上的当前日期和时间,偏移量设置为本地时间与协调世界时 (UTC) 的偏移量

那么WEBSITE_TIME_ZONE 设置会影响DateTime.Now 但不会影响DateTimeOffset.Now 是怎么回事?有什么办法可以解决这个问题吗?

澄清一点,我真的不想更改服务器上的时区。我们正在研究一个适当的时区独立解决方案。但我仍然很好奇为什么会这样。

【问题讨论】:

您真的需要更改服务器的时区吗?我会尽量避免这种要求。我同意这是 DateTimeOffset 的奇怪行为。现在,请注意... 我在讨论如何在 OP 中解释这一点。我宁愿不更改服务器的时区。就在探索选项时,我遇到了这个并且不明白它是如何工作的(或者为什么它不像我想象的那样工作)。所以我想我会试着澄清一下。 有道理 - 我完全愿意尝试你实际上不想做的事情:) 你可能不是第一个注意到那里有些奇怪的人:blogs.msdn.com/b/tomholl/archive/2015/04/07/…i.stack.imgur.com/9WyvQ.png***.com/a/29386241/397817 WEBSITE_TIME_ZONE 似乎根本没有更改时区我已将时区设置为 GMT,但我仍然看到 UTC 时间调整了一个小时以匹配时间将在格林威治标准时间:"Id":"UTC","DisplayName":"(UTC) Coordinated Universal Time","StandardName":"Coordinated Universal Time","DaylightName":"Coordinated Universal Time","BaseUtcOffset":"00:00:00","AdjustmentRules":null,"SupportsDaylightSavingTime":false 【参考方案1】:

我遇到了同样的问题。对我来说不幸的是,我继承了许多专门为东部标准时间编写的遗留代码,因此更新它以使用 UTC 基本上不是一种选择。

在深入研究 CLR 代码后,似乎是由于本地时区是根据系统注册表查找的。由于 Azure Web 应用程序在共享 VM 上运行,因此他们无法在不更改 CLR 代码的情况下正确支持这一点。

目前,我将在网站启动时通过以下反射黑客来解决这个问题,以欺骗 .Net 使其认为它是在东部标准时间。这不是一个很好的解决方案,如果他们更改 TimeZoneInfo 类的实现,很可能会中断,但希望他们更改它的原因是为了解决这个问题。

// rewrite local timezone
var tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var fInfo = typeof(TimeZoneInfo).GetField("s_cachedData", BindingFlags.Static|BindingFlags.NonPublic);
var cachedData = fInfo.GetValue(null);

fInfo = cachedData.GetType().GetField("m_localTimeZone", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
fInfo.SetValue(cachedData, tz);

【讨论】:

【参考方案2】:

对我来说,它现在有效。如果它不起作用,请确保设置正确的值

    打开注册表 搜索“时区” 检查您的区域是如何写入的。例如,我的区域是“东部东部标准时间 (+2)”,在注册表中它的名称是“E. Europe Standard Time”

所以我在 azure app "WEBSITE_TIME_ZONE: E. Europe Standard Time" 中添加了应用设置,它可以工作。

【讨论】:

这个答案有效,但 regedit 搜索有点傻(我正在寻找的值甚至不在我的注册表中)。这些值应该在某处发布,而不必这样做。无论如何,对于那些在日本的人来说,仅供参考,价值是“东京标准时间”。这里有一篇很棒的博文(仅限 Jp)blog.shibayan.jp/entry/20150909/1441725327 @starmandeluxe 最好是开始使用 UTC,现在我最终必须迁移到 UTC :( 这需要一点努力。 感谢您的建议!不幸的是,我和你在同一条船上,处理一个无法立即迁移的遗留代码库,因为版本需要不断发生。在这一点上,我只需要它工作。【参考方案3】:

对于那些偶然发现这个问题的人。这个问题已经修复很久了。

【讨论】:

以上是关于在 Azure Web 应用程序上更改时区不适用于 DateTimeOffset.Now?的主要内容,如果未能解决你的问题,请参考以下文章

DateTime.TryParse 在 Azure Web 应用程序中失败

WCF 服务的内部终结点不适用于 Azure Web 角色

Azure 队列触发器不适用于 Java

Azure 通知中心不适用于 ios

Mailchimp 不适用于生产 [laravel on azure]

azcopy 版本 10.x 不适用于 Azure 存储表的源和 Azure 存储 Blob 容器的目标