I have process that accepts datetime value with timezone as a string (data comes from outside system). I need to translate this datetime to what the time would have been at the local machines timezone.
Example code:
string cetId = "Central European Standard Time";
if (timeZone == "CET")
{
TimeZoneInfo cetZone = TimeZoneInfo.FindSystemTimeZoneById(cetId);
returnDateTime = TimeZoneInfo.ConvertTime(statusDateTime, cetZone, TimeZoneInfo.Local);
}
else if (timeZone == "CEST")
{
TimeZoneInfo cestZone = TimeZoneInfo.FindSystemTimeZoneById(cetId);
returnDateTime = TimeZoneInfo.ConvertTime(statusDateTime, cestZone, TimeZoneInfo.Local);
}
Do I need to do anything specific if the time is CEST (central european summer time) instead of CET (central european time) or does .net TimeZoneInfo object handle that scenario?
You should be fine.
You are telling ConvertTime what both time zones (source and target) are.
Do you have a specific problem with this or are you just asking for confirmation?
From TimeZoneInfo.ConvertTime()
The value of the Kind property of the dateTime parameter must correspond to the sourceTimeZone parameter, as the following table shows.
Just want to add that you need to watch out for the 'Kind' property of your StatusDateTime. In your case, it HAS to be 'Unspecified'. Check out the 'Remarks' section
I created a library a while back to encapsulate these kinds of transforms:
https://github.com/b9chris/TimeZoneInfoLib.Net/blob/master/TimeZoneInfoLib/TimeZone/UtcTimeZone.cs
Might be useful to you, or you may just want to pick it over to double-check your code. One of the things it encapsulates is #Brian's caveat - so it has explicit method names relating to the .Kind property, that throw useful exceptions if the .Kind is wrong. It also takes a little bit of the grunt work out of getting useful/common/daylight time names and abbreviations:
https://github.com/b9chris/TimeZoneInfoLib.Net/blob/master/TimeZoneInfoLib/TimeZone/TimeZoneShortNameMap.cs
Related
I've been struggling with this for a bit so I'll punt to SO.
I have an app where I need to parse strings into datetimes. The strings look like this:
"201503131557"
(they will always be this format "yyyyMMddHHmm") and always be in Central Standard Time (or Central Daylight Time depending on the date)even though they don't specify it.
When I parse them I understand that it parses them into local time. I'm running on Azure PaaS and don't want to change it to run in CST just to support this operation.
How do i write code that works both locally and in Azure PaaS that will correctly parse these dates into DateTimes setting their timezone to CST?
Here is a quick unit test I wrote to prove Matt Johnson's answer.
[TestMethod]
public void DateTests()
{
var unSpecDt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);
var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcDt = TimeZoneInfo.ConvertTimeToUtc(unSpecDt, tz);
var offset = tz.GetUtcOffset(unSpecDt);
var dto =new DateTimeOffset(unSpecDt, offset);
var cstDt = dto.DateTime;
Assert.IsTrue(cstDt.Hour - utcDt.Hour == offset.Hours);
}
To parse the string, since you have only the date and time, and you know the specific format the strings will be in, do this:
DateTime dt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);
The resulting value will have its Kind property set to DateTimeKind.Unspecified (not local time, as you thought). That is to be expected, as you provided no information regarding how this timestamp is related to UTC or local time.
You said the value represents time in Central Standard Time. You'll need a TimeZoneInfo object that understands that time zone.
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
Note that this identifier represents the Central Time observed in the USA, including both CST or CDT depending on which is in effect for the given value (despite the word "Standard" in its name). Also note that it valid on Windows operating systems only. If you wanted to use .NET Core on some other OS, then you'd need to pass the IANA identifier "America/Chicago" instead (or use my TimeZoneConverter library to use either identifier on any platform).
The next step is to figure out what you want to do with this value. You might do a few different things with it:
If you want to convert it to the equivalent UTC value, represented as a DateTime, then you can do this:
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
If you want a DateTimeOffset representation which holds the input you gave and the offset from UTC as it related to US Central Time, then you can do this:
TimeSpan offset = tz.GetUtcOffset(dt);
DateTimeOffset dto = new DateTimeOffset(dt, offset);
Keep in mind that it's possible for the input time is invalid or ambiguous if it falls near a DST transition. The GetUtcOffset method will return the standard offset in such cases. If you want different behavior, you have more code to write (out of scope for this post).
There are other things you might do, all of which are provided by the TimeZoneInfo class.
Note that "Azure PaaS" might refer to a few different things, and while there is a setting called WEBSITE_TIME_ZONE in Azure App Service - I don't recommend you lean on it. Consider it a last resort to be used only when you can't control the code. In most cases, it is better off writing your code to never depend on the time zone setting of the system it runs on. That means never calling DateTime.Now, or TimeZoneInfo.Local, DateTime.ToLocalTime, or even DateTime.ToUniversalTime (since it converts from the local time zone), etc. Instead, rely upon methods that work explicitly with either UTC or a specific time zone or offset. Then you will never need to care about where your app is hosted.
Lastly, understand that neither the DateTime or DateTimeOffset types have any capability of understanding that a value is tied to a specific time zone. For that, you'd need to either write your own class, or look to the Noda Time library whose ZonedDateTime class provides such functionality.
You can use:
DateTime.ParseExact(...)
public static DateTime ParseExact (string s, string format, IFormatProvider provider);
This datetime do not have any metadata about timezone. You can convert to UTC and then you will be sure that you are able to convert to all timezones.
Use the DateTime.TryParseExact(...) method with DateTimeStyles.RoundtripKind to avoid conversion.
DateTime dt;
DateTime.TryParseExact("201503131557", "yyyyMMddHHmm", null, System.Globalization.DateTimeStyles.RoundtripKind, out dt);
If you need to convert you will need to go to UTC then use the conversion methods of TimeZoneInfo with TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time").
I am using Facebook C# SDK to get some data from my Facebook page.
When I get objects of data, at that time I get one field:
created_time : 2014-05-23T11:55:00+0000
As it is not same as my current time how do I convert it to my current time or to standard UTC time?
For me the code:
DateTime.Parse("2014-05-23T11:55:00+0000").ToString()
returns
2014-05-23 12:55:00
Because 'DateTime.Parse()` understands the timezone in this string, and by default produces a local time. My timezone being Irish Summer Time, one hour ahead of UTC, that means 2014-05-23T12:55:00 for me, for you it'll be a different time depending on your timezone.
For the converse, to get the time parsed in UTC (more useful for behind-the-scenes web stuff or storage, rather than user interface), use DateTime.Parse("2014-05-23T11:55:00+0000").ToUniversalTime()
If you need to deal with timezones other than local to the machine the code is running on, or UTC, then you will need to use DateTimeOffset, with the exception that DateTimeParse will handle other timezones in the string, but from that point on only has the concepts of "local time", "universal time" and "unknown timezone".
I would use DateTimeOffset.ParseExact, specifying the format string an the invariant culture:
DateTimeOffset value = DateTimeOffset.ParseExact(text, "yyyy-MM-dd'T'HH:mm:ssK",
CultureInfo.InvariantCulture);
I strongly recommend this over using DateTime.Parse for the following reasons:
This always uses the invariant culture. It's explicitly stating that you don't want to use the local culture, which might have a different default calendar system etc
This specifies the format exactly. If the data becomes "10/06/2014 11:55:00" you will get an exception, which is better than silently guessing whether this is dd/MM/yyyy or MM/dd/yyyy
It accurately represents the data in the string: a date/time and an offset. You can then do whatever you want with that data, but separating the two steps is clearer
The first two of these can be fixed by using DateTime.ParseExact and specifying the culture as well, of course.
You can then convert that to your local time zone, or to any other time zone you want, including your system local time zone. For example:
DateTimeOffset localTime = value.ToLocalTime(); // Applies the local time zone
or if you want a DateTime:
DateTimeOffset localTime = value.ToLocalTime().DateTime;
It's just one extra line of code, but it makes it clearer (IMO) what you're trying to do. It's also easier to compare DateTimeOffset values without worrying about what "kind" they are, etc.
In fact, I wouldn't personally use DateTimeOffset or DateTime - I'd use OffsetDateTime from my Noda Time project, but that's a different matter.
My application is hosted on Windows Azure, which has all servers set to UTC.
I need to know when any given DateTime is subject to daylight savings time. For simplicity, we can assume that my users are all in the UK (so using Greenwich Mean Time).
The code I am using to convert my DateTime objects is
public static DateTime UtcToUserTimeZone(DateTime dateTime)
{
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");
var userDateTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
return DateTime.SpecifyKind(userDateTime, DateTimeKind.Local);
}
However, the following test fails at the last line; the converted DateTime does not know that it should be in daylight savings time.
[Test]
public void UtcToUserTimeZoneShouldWork()
{
var utcDateTime = new DateTime(2014, 6, 1, 12, 0, 0, DateTimeKind.Utc);
Assert.IsFalse(utcDateTime.IsDaylightSavingTime());
var dateTime = Utils.UtcToUserTimeZone(utcDateTime);
Assert.IsTrue(dateTime.IsDaylightSavingTime());
}
Note that this only fails when my Windows time zone is set to (UTC) Co-ordinated Universal Time. When it is set to (UTC) Dublin, Edinburgh, Lisbon, London (or any other northern-hemisphere time zone that observes daylight savings), the test passes. If you change this setting in Windows a restart of Visual Studio is required in order for the change to fully take effect.
What am I missing?
Your last line specifies that the value is in the local time zone of the system it's running in - but it's not really... it's converted using a different time zone.
Basically DateTime is somewhat broken, in my view - which makes it hard to use correctly. There's no way of saying "This DateTime value is in time zone x" - you can perform a conversion to find a specific local time, but that doesn't remember the time zone.
For example, from the docs of DateTime.IsDaylightSavingTime (emphasis mine):
This method determines whether the current DateTime value falls within the daylight saving time range of the local time zone, which is returned by the TimeZoneInfo.Local property.
Obviously I'm biased, but I'd recommend using my Noda Time project for this instead - quite possibly using a ZonedDateTime. You can call GetZoneInterval to obtain the ZoneInterval for that ZonedDateTime, and then use ZoneInterval.Savings to check whether the current offset contains a daylight savings component:
bool daylight = zonedDateTime.GetZoneInterval().Savings != Offset.Zero;
This is slightly long-winded... I've added a feature request to consider adding an IsDaylightSavingTime() method to ZonedDateTime as well...
The main thing you are missing is that "Greenwich Standard Time" is not the TimeZoneInfo id for London. That one actually belongs to "(UTC) Monrovia, Reykjavik".
You want "GMT Standard Time", which maps to "(UTC) Dublin, Edinburgh, Lisbon, London"
Yes, Windows time zones are weird. (At least you don't live in France, which gets strangely labeled as "Romance Standard Time"!)
Also, you should not be doing this part:
return DateTime.SpecifyKind(userDateTime, DateTimeKind.Local);
That will make various other code think it came from the local machine's time zone. Leave it with the "Unspecified" kind. (Or even better, use a DateTimeOffset instead of a DateTime)
Then you also need to use the .IsDaylightSavingsTime method on the TimeZoneInfo object, rather than the one on the .DateTime object. (There are two different methods, with the same name, on different objects, with differing behavior. Ouch!)
But I wholeheartedly agree that this is way too complicated and error prone. Just use Noda Time. You'll be glad you did!
I am writing a program in C# to convert between times from different countries (something like this). After trekking through Stack Overflow, most people seem to be interested in converting using time zone codes (such as from say GMT to EDT or EST to BST). This strikes me as a little odd because you need to then go through another hurdle to take DST complications into account.
What would be far simpler (and more practical, at least for my purposes) is to simply specify the country/city/state you wish to convert time from/to. If instead we just focus on local time for now, I have created these 2 functions to convert from Local time to FileTime (essentially UTC) and back again.
// Example use: convert_LocalToFile("1/11/2011 00:00:00") = 129645792000000000
long convert_LocalToFile(string time)
{
DateTime dt = DateTime.Parse(time);
return dt.ToFileTime();
}
// Example use: convert_FileToLocal(129645792000000000) = "1/11/2011 00:00:00"
string convert_FileToLocal(long time)
{
return DateTime.FromFileTime(time).ToString();
}
However, it would be great if we solved this once and for all, and had functions which allowed you to specify the country/city too. The spec would be as follows:
// Example use 1: convert_AnyToFile("1/11/2011 00:00:00", "England") = 129645792000000000
// Example use 2: convert_AnyToFile("1/11/2011 00:00:00","New York") = 129645936000000000
long convert_AnyToFile(string time, string location) {
...
}
// Example use 1: convert_FileToAny(129645792000000000, "England") = "1/11/2011 00:00:00"
// Example use 2: convert_FileToAny(129645936000000000,"New York") = "1/11/2011 00:00:00"
string convert_FileToAny(long time, string location) {
...
}
So my question is two-fold: Can someone 'fill in' the above two empty functions to make them work, and also provide a way to get C# to list all the countries and cities that would be allowed as parameters.
------------------------EDIT: Instead of the country or city, I would also make do with the obscure (to me anyway) TZ codes as shown from this page:
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
As has been pointed out, I would then need to find a data file to map from the tz database code to the country/city/region. In this case, substitute "string location" in the above 2 function templates with "string code". 'code' meaning the tz database time zone code (TZ), not the typical time zone code (such as EST or GMT).
As per comments some pointers:
For some conversion code see Creating a DateTime in a specific Time Zone in c# fx 3.5 and http://www.jarloo.com/c-convert-timezones/ .
For code to handle timezones as in tz_database (aka Olson...) see http://www.twinsun.com/tz/tz-link.htm and http://www.codeproject.com/KB/dotnet/Using_time_zones_in_NET.aspx .
MSDN references to relevant classes/methods etc.:
http://msdn.microsoft.com/en-us/library/system.datetime.aspx
http://msdn.microsoft.com/en-us/library/bb384267.aspx
http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx
http://msdn.microsoft.com/en-us/library/system.timezoneinfo.getsystemtimezones.aspx
UPDATE
After reading about NodaTime (didn't even know it existed) I strongly recommend to use it - see the answer of Jon Skeet.
As has been pointed out in a similar question, one needs to be careful since Windows' uses very misleading names (e.g.: the bizarre "Romance Standard Time" for Europe/Paris or "Eastern Standard Time" which strangely acts as ET and uses daylight saving time, when the official definition says otherwise. Not to mention US Eastern Standard Time).
Regarding mapping of cities/states/countries from Windows' Time Zones, I haven't yet found any data file for that, but I'll keep looking. I'm guessing one may need to find data to convert from Windows time zone names to Olson Time Zones, and then from there to individual cities/states/country names. This link will help with the former:
http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html
With that in mind, I've filled in the empty functions from the main question (thanks to Jon and Yahia for the pointers). The first one is the master function and is the one that will be useful for most people. The other two are secondary functions which the first function uses.
I've checked them and they work for daylight saving time, although I bet Jon Skeet and others will be able to find some ahem, 'minor' flaws. For example, dates before around 1601 won't work as Windows' File Time doesn't support that. It's also recommended to wrap calls to these functions in try/catch statements of course to trap false date input etc.
// Master conversion function
// Example use 1: convertTimezone("1/11/2011 00:00:00", "GMT Standard Time", "Eastern Standard Time") = "31/10/2011 20:00:00"
// Example use 2: convertTimezone("1/11/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/11/2011 04:00:00"
// Example use 3: convertTimezone("1/10/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/10/2011 05:00:00"
string convertTimezone(string time, string oldlocation, string newlocation)
{
long l = convertTime_AnyToFile(time, oldlocation);
string newtime = convertTime_FileToAny(l, newlocation);
return newtime;
}
// Example use 1: convertTime_AnyToFile("1/11/2011 00:00:00", "GMT Standard Time") = 129645792000000000
// Example use 2: convertTime_AnyToFile("1/11/2011 00:00:00","Eastern Standard Time") = 129645936000000000
long convertTime_AnyToFile(string time, string location)
{
DateTime a = DateTime.Parse(time );
DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location, "UTC");
return b.ToFileTime();
}
// Example use 1: convertTime_FileToAny(129645792000000000, "GMT Standard Time") = "1/11/2011 00:00:00"
// Example use 2: convertTime_FileToAny(129645936000000000,"Eastern Standard Time") = "1/11/2011 00:00:00"
string convertTime_FileToAny(long time, string location)
{
DateTime a = DateTime.FromFileTimeUtc(time);
DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location);
return b.ToString();
}
Although it appears to work okay (under the limited tests I've done), before I 'tick' my own answer, I might wait for some feedback first as maybe someone can improve the above code.
If you're content to use the zoneinfo/Olson names (e.g. "Europe/London", "America/Los_Angeles" etc) you could look at the project I started, Noda Time. It's generally a port of the Joda Time calendar engine, but with a new API to be more .NET-centric.
It's not at v1 yet due to a few missing features, but what's there should work well enough. Note that it addresses many of the deficiencies of DateTime, in particular distinguishing between a "local date/time" and a "zoned date/time" (and also coping with just a time or just a date). There are conversions to and from DateTime if you only want to use Noda Time for time zone conversions, of course - although I'd recommend using it pervasively within your code if you can. (And where it doesn't provide all the features you want, please let us know so that we can add them!)
Note that when treating a local time as being in a particular time zone, you need to be aware of the possibility that it could be either ambiguous or never existed. For example on Sunday the clocks went back in the UK, so 1:30am occurred twice. In spring, 1:30am wouldn't occur at all as the clocks go from 1am to 2am. Of course, Noda Time provides different options for handling this, but you do need to work out what you want to do in each case :)
We are developing a C# application for a web-service client. This will run on Windows XP PC's.
One of the fields returned by the web service is a DateTime field. The server returns a field in GMT format i.e. with a "Z" at the end.
However, we found that .NET seems to do some kind of implicit conversion and the time was always 12 hours out.
The following code sample resolves this to some extent in that the 12 hour difference has gone but it makes no allowance for NZ daylight saving.
CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
As per this date site:
UTC/GMT Offset
Standard time zone: UTC/GMT +12 hours
Daylight saving time: +1 hour
Current time zone offset: UTC/GMT +13 hours
How do we adjust for the extra hour? Can this be done programmatically or is this some kind of setting on the PC's?
For strings such as 2012-09-19 01:27:30.000, DateTime.Parse cannot tell what time zone the date and time are from.
DateTime has a Kind property, which can have one of three time zone options:
Unspecified
Local
Utc
NOTE If you are wishing to represent a date/time other than UTC or your local time zone, then you should use DateTimeOffset.
So for the code in your question:
DateTime convertedDate = DateTime.Parse(dateStr);
var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified
You say you know what kind it is, so tell it.
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(dateStr),
DateTimeKind.Utc);
var kind = convertedDate.Kind; // will equal DateTimeKind.Utc
Now, once the system knows its in UTC time, you can just call ToLocalTime:
DateTime dt = convertedDate.ToLocalTime();
This will give you the result you require.
I'd look into using the System.TimeZoneInfo class if you are in .NET 3.5. See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. This should take into account the daylight savings changes correctly.
// Coordinated Universal Time string from
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z";
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date);
DateTime utcDateTime = localDateTime.ToUniversalTime();
// ID from:
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
TimeZone.CurrentTimeZone.ToLocalTime(date);
DateTime objects have the Kind of Unspecified by default, which for the purposes of ToLocalTime is assumed to be UTC.
To get the local time of an Unspecified DateTime object, you therefore just need to do this:
convertedDate.ToLocalTime();
The step of changing the Kind of the DateTime from Unspecified to UTC is unnecessary. Unspecified is assumed to be UTC for the purposes of ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx
I know this is an older question, but I ran into a similar situation, and I wanted to share what I had found for future searchers, possibly including myself :).
DateTime.Parse() can be tricky -- see here for example.
If the DateTime is coming from a Web service or some other source with a known format, you might want to consider something like
DateTime.ParseExact(dateString,
"MM/dd/yyyy HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
or, even better,
DateTime.TryParseExact(...)
The AssumeUniversal flag tells the parser that the date/time is already UTC; the combination of AssumeUniversal and AdjustToUniversal tells it not to convert the result to "local" time, which it will try to do by default. (I personally try to deal exclusively with UTC in the business / application / service layer(s) anyway. But bypassing the conversion to local time also speeds things up -- by 50% or more in my tests, see below.)
Here's what we were doing before:
DateTime.Parse(dateString, new CultureInfo("en-US"))
We had profiled the app and found that the DateTime.Parse represented a significant percentage of CPU usage. (Incidentally, the CultureInfo constructor was not a significant contributor to CPU usage.)
So I set up a console app to parse a date/time string 10000 times in a variety of ways. Bottom line:
Parse() 10 sec
ParseExact() (converting to local) 20-45 ms
ParseExact() (not converting to local) 10-15 ms
... and yes, the results for Parse() are in seconds, whereas the others are in milliseconds.
I'd just like to add a general note of caution.
If all you are doing is getting the current time from the computer's internal clock to put a date/time on the display or a report, then all is well. But if you are saving the date/time information for later reference or are computing date/times, beware!
Let's say you determine that a cruise ship arrived in Honolulu on 20 Dec 2007 at 15:00 UTC. And you want to know what local time that was.
1. There are probably at least three 'locals' involved. Local may mean Honolulu, or it may mean where your computer is located, or it may mean the location where your customer is located.
2. If you use the built-in functions to do the conversion, it will probably be wrong. This is because daylight savings time is (probably) currently in effect on your computer, but was NOT in effect in December. But Windows does not know this... all it has is one flag to determine if daylight savings time is currently in effect. And if it is currently in effect, then it will happily add an hour even to a date in December.
3. Daylight savings time is implemented differently (or not at all) in various political subdivisions. Don't think that just because your country changes on a specific date, that other countries will too.
#TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
Don't forget if you already have a DateTime object and are not sure if it's UTC or Local, it's easy enough to use the methods on the object directly:
DateTime convertedDate = DateTime.Parse(date);
DateTime localDate = convertedDate.ToLocalTime();
How do we adjust for the extra hour?
Unless specified .net will use the local pc settings. I'd have a read of: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx
By the looks the code might look something like:
DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year );
And as mentioned above double check what timezone setting your server is on. There are articles on the net for how to safely affect the changes in IIS.
In answer to Dana's suggestion:
The code sample now looks like:
string date = "Web service date"..ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate);
The original date was 20/08/08; the kind was UTC.
Both "convertedDate" and "dt" are the same:
21/08/08 10:00:26; the kind was local
I had the problem with it being in a data set being pushed across the wire (webservice to client) that it would automatically change because the DataColumn's DateType field was set to local. Make sure you check what the DateType is if your pushing DataSets across.
If you don't want it to change, set it to Unspecified
I came across this question as I was having a problem with the UTC dates you get back through the twitter API (created_at field on a status); I need to convert them to DateTime. None of the answers/ code samples in the answers on this page were sufficient to stop me getting a "String was not recognized as a valid DateTime" error (but it's the closest I have got to finding the correct answer on SO)
Posting this link here in case this helps someone else - the answer I needed was found on this blog post: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - basically use DateTime.ParseExact with a format string instead of DateTime.Parse
This code block uses universal time to convert current DateTime object then converts it back to local DateTime. Works perfect for me I hope it helps!
CreatedDate.ToUniversalTime().ToLocalTime();