Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get DateTimeOffset from DateTime (utc) and TimeZoneInfo

Tags:

c#

datetime

I need to convert DateTime+TimeZoneInfo into DateTimeOffset.

How do I do this? I assume I have to pass TimeSpan but then I'm not sure if daylight saving times will be handled properly..

Thanks!

UPDATE

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow, timeZone.BaseUtcOffset);

This code throws exception..

The UTC Offset for Utc DateTime instances must be 0.\r\nParameter name: offset

UPDATE 2

Sorry, I didn't realize that DateTimeOffset contains only offset, it doesn't contain actual zone information - so I'm accepting answer from @Dave as it is what I will be using..

like image 557
katit Avatar asked Jun 08 '11 19:06

katit


People also ask

Is DateTimeOffset always UTC?

DateTimeOffset reflects a time's offset from UTC, but it does not reflect the actual time zone to which that offset belongs. For details about time values and support for time zones, see Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo.

Does DateTimeOffset have timezone?

A DateTimeOffset value isn't tied to a particular time zone, but can originate from a variety of time zones. The following example lists the time zones to which a number of DateTimeOffset values (including a local Pacific Standard Time) can belong.

Is DateTimeOffset better than DateTime?

DateTime values lack any knowledge of time zone, or lack thereof. If you need to know when things actually occurred, with more precision than just the approximate date, and you can't be 100% sure that your dates are ALWAYS stored in UTC, then you should consider using DateTimeOffset to represent your datetime values.

How do I get DateTimeOffset offset?

You can also get the DATENAME(tz, @datetimeoffset) to get the offset as a varchar. TZOFFSET works in place of tz and, for what it's worth, is recognized by the SSMS syntax highlighter.


3 Answers

You should be about to get the difference between DateTime.UtcNow and DateTime.Now

var now = DateTime.Now;
var utcNow = now.ToUniversalTime();
var ts = utcNow - now;

If you are saving the offset, it is usually beneficial to save all dates in UTC (especially in a db) so you won't have to deal with offsets. You simply convert them before displaying but do all calculations in UTC.

Edit: If you have a TimeZone object, you can convert a UTC date to the local time for that time zone.

TimeZone.CurrentTimeZone.ToLocalTime()

OR

DateTime dt = TimeZoneInfo.ConvertTimeFromUtc()

Here's some sample code that will list a date in all timezones.

var dt = new DateTime(2011, 5, 21, 11, 0, 0);
foreach (var tzi in TimeZoneInfo.GetSystemTimeZones())
{
    Console.WriteLine(string.Format("Time in {0} is {1}", tzi.DisplayName, TimeZoneInfo.ConvertTimeFromUtc(dt, tzi)));
}
like image 186
Dave Ferguson Avatar answered Nov 04 '22 00:11

Dave Ferguson


TimeZoneInfo has a BaseUtcOffset property that is a TimeSpan representing the offset.

This is the offset that the DateTimeOffset constructors expects:

var myDTOffset = new DateTimeOffset(myDatetime, mytzInfo.BaseUtcOffset);
like image 38
Oded Avatar answered Nov 03 '22 23:11

Oded


I think there may be an easier solution to eliminate the error. You tried:

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow, timeZone.BaseUtcOffset);

DateTimeOffset throws an exception. What you wanted is this:

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow).ToOffset(timeZone.BaseUtcOffset);

This will not throw the exception. I'm not sure why the constructor that accepts a TimeSpan even exists, since it only works if it matches the local or utc offset given in the DateTime object. But it is still possible with less headache.

like image 45
Garr Godfrey Avatar answered Nov 03 '22 22:11

Garr Godfrey