Reputation: 74605
I've read many SO articles, but I don't seem to be able to find a good answer to the problem. Posted suggestions include functions that convert dates to and from strings more then once, concatenating bits on the end and it all just seems... messy
So to the problem:
We have servers around the world. All servers run in their own local time and keep logs with time entries that are local to the server. Some servers are in DST observing areas, others arent
Suppose I have these strings from a log: 2013-01-01 12:34:56, 2013-07-01 12:34:56 And I know that this server is in New York so it's UTC-5 or UTC-4 when DST is in operation
And I have the same strings from a log on a server in Hong Kong, where DST does not apply and the time zone is +8
What I'm after is a block of code where I can tell it:
And the code will parse the string into a DateTimeOffset, where the offset is adjusted according to DST if the time being parsed is DST relevant
For example: NY server log says "2013-01-01 ..." DST does NOT apply to this date in JANUARY so the date parsed should be: 12:34:56 in new york time, a.k.a 17:34:56 in UTC (because it's -5, no DST)
NY server log says "2013-07-01 ..." DST DOES apply to this date in june so the date parsed should be: 12:34:56 in new york time, a.k.a 16:34:56 in UTC (because it's -4, with the DST)
HK server, both date times parse to 04:34:56 UTC
Thanks guys
Upvotes: 3
Views: 2948
Reputation: 6660
To get the UTC-times of the time logged in the different log files you will need to know the names of the local time zones. Then you can use the DateTimeOffset
-struct TimeZoneInfo
-class to calculate the UTC-times:
public DateTime ParseAsUtc(string logDate, string timezoneName)
{
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timezoneName);
var localDate = DateTime.Parse(logDate);
var offset = new DateTimeOffset(localDate, timeZone.GetUtcOffset(localDate));
return offset.ToUniversalTime().DateTime;
}
ParseAsUtc("2013-01-01 12:34:56", "Eastern Standard Time"); //01.01.2013 17:34:56
ParseAsUtc("2013-07-01 12:34:56", "Eastern Standard Time"); //01.07.2013 16:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time"); //01.01.2013 04:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time"); //01.07.2013 04:34:56
Upvotes: 5
Reputation: 1500825
Firstly, I'd strongly recommend that you change the system to log in UTC everywhere. It'll make your life much simpler.
If you're really stuck with what you've got, you should use DateTime.TryParseExact
with a DateTimeStyles
of just 0 (the default). That will give you a value with a DateTimeKind
of Unspecified
, which is what you want. (It's not UTC, and it's not local to the machine doing the parsing.)
You can then use TimeZoneInfo.GetUtcOffset
(with the right time zone for that log) to work out the offset, and create a DateTimeOffset
from the two together.
As a completely biased aside, you could also change to use the Noda Time project I maintain, which will allow your code to be much simpler to understand :)
Upvotes: 6