处理客户端和服务器之间的时区,仅限日期DateTime

时间:2018-03-02 04:32:16

标签: c# datetime asp.net-web-api timezone utc

我的ASP.NET Web API应用程序中有一个自定义验证属性,用于检查日期是否在未来(不允许将来的日期)。这是代码:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    if (value != null)
    {
        var date = (DateTime)value;
        if (date != null)
        {
            if(date.Date > DateTime.UtcNow.Date)
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), new[] { validationContext.MemberName });
            }
        }
    }

    return ValidationResult.Success;
}

我无法弄清楚如何进行比较,因此适用于所有时区。使用DateTime.UtcNow不是解决方案,因为如果客户端和服务器位于同一时区,则在接近午夜的时间内,日期将是后一天。当然,DateTime.Now不适用于其他时区。那么,解决方案是什么?

更新

在我的WebApiConfig.cs文件中,我使用此代码将DateTimeZoneHandling设置为Utc

jsonFormatter.SerializerSettings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateTimeZoneHandling = DateTimeZoneHandling.Utc
};

这将在JSON响应中格式化日期,如下所示:“2018-03-02T00:00:00Z”。

并且,来自客户端的所有DateTime值都将Kind属性设置为Utc。然后,我可以将日期与UtcNow进行比较,但现在问题是“2018-03-02T00:00:00Z”日期在我的浏览器中显示为2018年3月1日,因为它被转换为当地时间(UTC -5)。

3 个答案:

答案 0 :(得分:2)

只有两种可行的方法。

  1. 在将值发送到服务器进行比较之前,在客户端上转换为UTC。
  2. 尝试确定客户端的时区ID(或仅针对单个时间点的偏移),并将其从客户端传递到服务器。然后,服务器可以在比较之前使用该信息进行UTC转换。
  3. 如果您不同时使用这些选项,只将客户端本地时间值传递给服务器而没有任何偏移或时区信息,则无法实现目标。服务器没有关于客户端时区的魔力。

    此外,如果您要比较整个日期(前2018-03-02,而不是2018-03-02T00:00:00),那么您需要确定哪个时区与您的用例相关。例如,如果您与UTC日进行比较,那么除非他们将业务流程与UTC对齐,否则这对于洛杉矶的企业来说效果不佳。

    根据我们的聊天更新:

    由于您只需要处理整个日期,因此请勿进行任何时区转换。确保从datepicker中选择的日期与发送的完全相同 - 而不是通过Date对象。如果您的日期选择器没有直接提供此值,则可以从Date对象创建它 - 手动或使用像moment.js这样的库。请勿拨打.toISOString(),因为除了ISO格式之外,它还会假设您指当地时间午夜并进行UTC转换。

    也不要设置任何JSON.Net的日期设置 - 只需使用默认设置。

答案 1 :(得分:0)

试试这个:

var date = (DateTime)value;
var utcDate = date.ToUniversalTime();

并且胜过这样:

if(utcDate .Date > DateTime.UtcNow.Date)

答案 2 :(得分:0)

var timezoneOffset = new Date().getTimezoneOffset(); - 您可以从客户端到服务器(任何 Web API 调用)获取此信息

借助 timezoneoffset 详细信息,您可以实现相同的目标。在我的情况下,我将 UTC DateTime 转换为服务器端的客户端本地日期时间。

DateTime clientDateTime = DateTime.UtcNow - new TimeSpan(timezoneOffset / 60, timezoneOffset % 60, 0);

相关问题