Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get UTC DateTime from query string

Assume we have action:

[HttpGet]
public Task<IActionResult> Foo(DateTime date)
{
    var utc = date.ToUniversalTime();
}

It seems like MVC framework by default convert UTC DateTime to Local (somewhere in middleware). How can I turn off this behaviour and get rid of additional transformations?

UPD:

Chrome dev. console (network tab) shows me such query parameter: date:2017-12-01T00:00:00.000Z

but in controller I see: {01/12/2017 03:00:00}

like image 700
Dzmitry Martavoi Avatar asked Dec 11 '17 16:12

Dzmitry Martavoi


People also ask

How do I pass dateTime in query string?

string dateTime = Request. QueryString["DateStarted"]; DateTime dt = Convert. ToDateTime(dateTime); Response.

What is UTC time string?

UTC, or Universal Time Coordinated, is the most precise and commonly referred to time standard. Since the 1970s, this time standard has been globally used as the most precise time standard, instead of formerly used GMT standard, which has turned now into a regular time zone.

What is UTC dateTime format?

Times are expressed in UTC (Coordinated Universal Time), with a special UTC designator ("Z"). Times are expressed in local time, together with a time zone offset in hours and minutes. A time zone offset of "+hh:mm" indicates that the date/time uses a local time zone which is "hh" hours and "mm" minutes ahead of UTC.


1 Answers

DateTime should not be used when accurate timezone-based times are necessary. That's why DateTimeOffset exists. By default, DateTime.Kind is DateTimeKind.Unspecified. In other words, it's up to you, after post, to determine what it should be interpreted as. The problem is that you can really only assume DateTimeKind.Utc, as that's the only thing you can interpret as a DateTime correctly. Posting the user's local time leaves you stranded, because DateTimeKind.Local actually means the server's local time, which usually will not the be same as the client's.

However, even in HTML5, posting a full datetime with timezone is virtually impossible. Although input types such as datetime and datetime-local exist, they are not implemented in any major browser. If you want to post dates with times and timezone, then you'll actually need three properties on your view model:

public DateTime Date { get; set; }
public TimeSpan Time { get; set; }
public string TimeZone { get; set; }

The TimeZone property assumes you'll use a dropdown list composed of values from TimeZoneInfo.GetSystemTimeZones(). If you want to use a different setup, you'll need some way to map to/from those values, since that's all you have to work with in C# to get an offset. However, you could simply allow the user to post an offset, instead, but that's less user-friendly, and may be difficult for some users. In particular, they would need to understand not only what the concept "offset from UTC" means, but also that take into account the current status of daylight savings time and adjust that offset according to the actual date.

Regardless, each of these properties can easily be mapped to a input type: date/time and a select/time in the case of the TimeZone, depending on whether you go with a dropdown or an manual offset entry. They are also all easily mapped back onto your view model by the modelbinder following a post. You then just need to create a DateTimeOffset from that information, which is what you'd actually persist on your entity class.

var offset = TimeZoneInfo
    .FindTimeZoneById(model.TimeZone)
    .GetUtcOffset(model.Date)
var dateTimeOffset = new DateTimeOffset(model.Date.Add(model.Time), offset);
like image 88
Chris Pratt Avatar answered Oct 05 '22 12:10

Chris Pratt