Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
606 views
in Technique[技术] by (71.8m points)

c# - Handling time-zone between client and server for date-only DateTime

I have a custom validation attribute in my ASP.NET Web API application that checks if the date is in the future or not (dates in the future are not allowed). Here's the code:

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;
}

I can't figure out how to make the comparison so it works for all time-zones. Using DateTime.UtcNow is not the solution, because if the client and the server are in the same timezone, in the hours close to midnight, the date will be the day after. And, of course DateTime.Now wouldn't work for other time-zones. So, what's the solution?

Update:

In my WebApiConfig.cs file, I have this code to set the DateTimeZoneHandling to Utc:

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

This will format the date in the JSON response like this: "2018-03-02T00:00:00Z".

And, all the DateTime values coming from the client will have their Kind property set to Utc. Then, I can compare the date with UtcNow, but now the problem is the date "2018-03-02T00:00:00Z" is displayed as March 1, 2018 in my browser, because it is converted to local time (UTC -5).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are only two viable approaches.

  1. Convert to UTC on the client before sending the value to the server for comparison.
  2. Try to determine the client's time zone id (or offset if just for a single point in time), and pass that from the client to the server. The server can then use that information to do the conversion to UTC before comparison.

If you take neither of these options, passing only a client-local-time value to the server without any offset or time zone information, then there is no way to accomplish your goal. There is no magic the server has about what the client's time zone may be.

Also, if you are comparing whole dates (ex 2018-03-02, not 2018-03-02T00:00:00), then you will need to decide which time zone is relevant for your use case. For example, if you compare against UTC day, that is not going to work well for a business in Los Angeles unless they have aligned their business processes to UTC.

Update per our chat:

Since you only need to work with whole dates, then don't do any time zone conversions. Make sure whatever date is chosen from your datepicker is exactly what is sent - rather than going through the Date object. If your datepicker doesn't offer this value directly, then create it from the Date object - either manually or with a library like moment.js. Don't call .toISOString() because in addition to ISO format, it will also assume you meant midnight local time and do a UTC conversion.

Also don't set any of JSON.Net's date settings - just use the defaults.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...