ValueProviderResult.ConvertTo在本地和云中返回不同的日期

时间:2019-06-03 10:05:58

标签: .net datetime timezone globalization azure-cloud-services

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

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;

问题在于此资料夹在本地和远程返回不同的日期。

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

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

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

1 个答案:

答案 0 :(得分:1)

几件事:

  • 文化设置和时区是完全正交的概念。文化可能会影响字符串的格式或应用的日历系统,但不会影响时区。他们彼此无关。

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

  • 您没有向我们展示如何应用此模型绑定程序或如何使用API​​。假设您的API正确交付了基于UTC的结果(使用Z),那么您对时区的担忧完全基于客户端代码的解释。

  • 直接回答“还有什么会导致不同的时区?”

    • 如果您调用DateTime.NowDateTimeOffset.NowTimeZoneInfo.Local或使用DateTimeKind.Local.ToLocalTime()等,以及几种转换的API,像.ToUniversalTime()这样的本地时间,那么服务器的本地时区设置(来自日期和时间控制面板或设置页面)就是控制该时区的方法。它是服务器上所有应用程序的服务器范围设置。您也可以在命令行上使用tzutil.exe查看或控制它。
    • 如果您遵循的最佳做法(不依赖服务器的时区设置)(仅使用基于UTC的API或使用特定时区的API),则您不必担心。
    • 别忘了世界并非都在一个时区。因此,如果您的服务器在一个时区(例如UTC)发出时间,并且您的客户端代码正在将其显式或隐式转换为另一个时区(例如其本地时间),则值的差异是完全正常的。 / li>