ValueProviderResult.ConvertTo returns 本地和云端的不同日期

ValueProviderResult.ConvertTo returns different dates locally and in the cloud

我有下一个自定义模型活页夹:

public class WebApiModelBinderDateTime : IModelBinder
{
    public bool BindModel(HttpActionContext executionContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (value == null)
        {
            return false;
        }

        DateTime date = (DateTime)value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);
        date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
        bindingContext.Model = date;

        return true;
    }
}

文化在 web.config 中设置如下:

<globalization culture="en-GB" enableClientBasedCulture="false" uiCulture="en-GB" />

并且在 global.asax 中是这样的:

CultureInfo culture = CultureInfo.CreateSpecificCulture("en-GB");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;

问题是这个活页夹 returns 本地和远程日期不同。

例如2019-06-03T09:53:26.651Z 将在本地转换为 2019-06-03 10:53:26,但在云中转换为 2019-06-03 09:53:26(这是部署到 Azure 云服务的旧系统)。

我尝试在本地和远程进行调试,但没有发现 CultureInfo.CurrentCultureModelBindingContextValueProviderValueProviderResult 之间有任何差异。

还有什么会导致不同的时区?

几件事:

  • 文化设置和时区是完全正交的概念。文化可以影响字符串的格式,或者应用哪个日历系统,但它不影响时区。他们之间没有任何关系。

  • 您正在指定 DateTimeKind.Utc,因此无论您在哪里使用它,结果值都将被序列化,并带有一个表示 UTC 的尾随 Z。如果这些值确实是基于 UTC 的,那么一切都很好,没有什么可做的了。但是,如果您将这些应用于可能代表不同时区时间的任意值,则设置 UTC 类型将无济于事。相反,您可以考虑使用 DateTimeOffset 类型而不是 DateTime.

  • 您没有向我们展示您如何应用此模型绑定器或如何使用 API。假设您的 API 正确地传递了 UTC-based 结果(使用 Z),那么您对时区的担忧完全基于 client-side 代码的解释。

  • 直接回答"What else can cause different time zones?"

    • 如果调用DateTime.NowDateTimeOffset.NowTimeZoneInfo.Local或使用DateTimeKind.Local.ToLocalTime()等,还有几个APIs 将 本地时间转换为 .ToUniversalTime(),然后服务器的本地时区设置(从日期和时间控制面板或设置页面)控制该时区。它是服务器上所有应用程序的 server-wide 设置。您也可以在命令行中使用 tzutil.exe 查看或控制它。
    • 如果您遵循 而非 依赖于服务器时区设置的最佳实践,(通过仅使用基于 UTC 的 APIs 或 APIs使用特定时区),那么您就没有这个顾虑。
    • 别忘了,世界并非都在同一个时区。因此,如果您的服务器在一个时区(例如 UTC)发出时间,而您的客户端代码显式或隐式地将其转换为另一个时区(例如本地时间),那么值不同是完全正常的。