.NET: Accounting for daylight savings
I have a method that creates a UTC DateTime
from user input, using the GMT offset of their geographical position:
public static DateTime LocalToUtc
(int year, int month, int day, int hour, decimal gmtOffset) {
// argument validation here
var dateTime = new DateTime(year, month, day).AddHours(hour);
var dateTimeOffset =
new DateTimeOffset(dateTime, TimeSpan.FromHours(gmtOffset));
return dateTimeOffset.UtcDateTime;
}
The problem is that this function is 开发者_运维技巧off by an hour if it's daylight savings in the user's timezone.
So while my personal GMT offset is -8, the current timezone offset is -7 because of daylight savings.
How do I change the function above to account for daylight savings? Don't I somehow need to create some timezone object from the GMT offset and get its timezone offset?
There is no way to do it without knowing the actual time zone: several time zones have the same base UTC offset, but with different rules for daylight saving time. For instance, W. Europe Standard Time and W. Central Africa Standard Time both have an offset of +01:00, but the former supports DST while the latter doesn't. So the offset is not enough to decide whether DST applies or not...
Your method should take a TimeZoneInfo
parameter instead of gmtOffset
. This way you can just use the TimeZoneInfo.ConvertTime
method to convert the date, it will automatically take DST into account.
DateTime already has methods to do this called ToLocalTime()
and ToUniversalTime()
. What's wrong with using that?
EDIT:
Based upon the comment that the author is looking to convert to utc from a timezone other than the current computers timezone, then I refer you to John Skeets answer Here
From the MSDN documentation:
string displayName = "(GMT+06:00) Antarctica/Mawson Time";
string standardName = "Mawson Time";
TimeSpan offset = new TimeSpan(06, 00, 00);
TimeZoneInfo mawson = TimeZoneInfo.CreateCustomTimeZone(standardName,
offset, displayName, standardName);
Console.WriteLine("The current time is {0} {1}",
TimeZoneInfo.ConvertTime(DateTime.Now,
TimeZoneInfo.Local, mawson), mawson.StandardName);
You should use the TimeZone.GetUtcOffset
Method if you don't want to use the built-in UTC method.
http://msdn.microsoft.com/en-us/library/system.timezone.getutcoffset.aspx
It will give you your offset to UTC. You could also use the built-in methods to get UTC time from local times.
http://msdn.microsoft.com/en-us/library/system.datetime.touniversaltime(v=VS.100).aspx
Since it sounds you're asking users for a time offset that might not necessarily be in the machine's local time zone, the local machine time wouldn't work. But using the TimeZoneInfo class, you should be able to construct an instance that accounts for the offset and DST status and use the built-in methods from there.
Edit: On my machine, at least, TimeZoneInfo.GetSystemTimeZones()
seems to return all valid time zones. This could be easily mapped to a drop-down menu to allow the user to select.
精彩评论