katit
katit

Reputation: 17915

get DateTimeOffset from DateTime (utc) and TimeZoneInfo

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..

Upvotes: 26

Views: 50676

Answers (4)

Dave Ferguson
Dave Ferguson

Reputation: 1456

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

Upvotes: 23

Geoduck
Geoduck

Reputation: 9009

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.

Upvotes: 4

rdans
rdans

Reputation: 2157

For those of us working with legacy systems, its not always possible to change the way the data is stored. If you are only interested in the specific time zone on the machine from which your code is running, you can use the below extension method. There is an implicit conversion between DateTime and DateTimeOffset which takes into account the "DateTime.Kind" property.

public static DateTimeOffset ToDateTimeOffset(this DateTime dt)
{
    return DateTime.SpecifyKind(dt, DateTimeKind.Local);
}

Upvotes: 2

Oded
Oded

Reputation: 499312

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

Upvotes: 7

Related Questions