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 instance开发者_如何转开发s 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..
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)));
}
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);
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.
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);
}
精彩评论