Reputation: 12646
My end goal is to get universal time from client with NO offset - just UTC time. I try to accomplish this like so:
Javascript: (new Date()).toUTCString()
, the output of which logs: Thu, 17 Mar 2016 15:13:23 GMT
, which is exactly what I need.
Then I take it to server and try to convert it to DateTimeOffset
:
string dateTimeOffsetPattern = "ddd, dd MMM yyyy HH:mm:ss 'GMT'";
DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
(timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture);
Which results in:
3/17/2016 3:13:23 PM -04:00
Somehow it adjusts the time for my local (Eastern) offset. I do NOT want this to happen, I want it to just return the UTC time, like so:
3/17/2016 3:13:23 PM +00:00
P.S. I did just ask another question about this, and I apologize, since I feel like it should be easy enough, but I don't get it. This should be really simple, but it looks like offset doesn't have a setter (unless I am completely missing some C# basics as usual):
public TimeSpan Offset { get; }
Upvotes: 7
Views: 13713
Reputation: 12497
I would parse from JS normally, then do the following:
OffSet
from DateTimeOffset
by returning DateTime
OffSet
by instantiating another DateTimeOffset
having TimeSpan
set to ZERO
.In your case:
var clientLoginTime = new DateTimeOffset(clientLoginTime.DateTime, TimeSpan.FromHours(0));
This can be easily converted into an extension method
public static DateTimeOffset SetOffset(this DateTimeOffset dto, int timeZoneDiff)
{
return new DateTimeOffset(dto.DateTime, TimeSpan.FromHours(timeZoneDiff));
}
Upvotes: 5
Reputation: 62238
From JavaScript (or any other client) you should send DateTimes using ISO8601 format which would be yyyy-MM-ddTHH-mm-ss.sssz
. The Z indicates that the datetime instance is GMT (UTC). You can also change this to add + or - from GMT. You can do this using the JavaScript Date object using myDate.toISOString()
When creating your WebAPI model(s) you can then use either a DateTime
or DateTimeOffset
types directly. The JSON.NET serializer for Web API will automatically deserialize the sent ISO8601 datetime string to the correct DateTime or DateTimeOffset type (depending on which one you are using). This means that you do not have to do any manuall parsing in your code which is good. (Imagine if you had to send everything as string and parse everything manually in all your methods?).
So you can now have a method
public async Task<IHttpActionResult> GetRecords(DateTimeOffset? startFrom)
And the startFrom
will automatically be populated based on the sent ISO8601 formatted DateTime string.
Finally, the last and most import reason to do this is that your clients will probably not all use the same locale. You could have a user that has their browser set to Spanish so .toUTCString()
will not yield an English string or possibly even a string with mm/dd but the reverse (like most countries other than the USA).
Long story short for WebAPI
Upvotes: 2
Reputation: 21887
There's an overload of ParseExact
where you can specify a DateTimeStyles
. One of the values of DateTimeValues
is AssumeUniversal
, which says:
If format does not require that input contain an offset value, the returned DateTimeOffset object is given the UTC offset (+00:00).
which basically means "don't assume it's local, assume it's universal." Assuming local is the default, which is why you're seeing the result you are in that it's adjusting to local. Specifying AssumeUniversal
should parse it the way you want.
DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
(timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal);
Upvotes: 7