94

I'm trying to use DateTimeOffset to convey a specific moment in time across any time zone. I can't figure out how to use TimeZoneInfo to deal with daylight saving time.

var dt = DateTime.UtcNow;
Console.WriteLine(dt.ToLocalTime());

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
Console.WriteLine(utcOffset.ToOffset(tz.BaseUtcOffset));

This prints out:

6/2/2010 4:37:19 PM
6/2/2010 3:37:19 PM -06:00

I am in the central time zone, and and we are currently in daylight saving time. I am trying to get the second line to read:

6/2/2010 4:37:19 PM -05:00

BaseUtcOffset apparently doesn't change based on DST.

How can I get the the right time with the proper offset value?

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
jaminto
  • 3,895
  • 3
  • 32
  • 36

5 Answers5

78

You can also use TimeZoneInfo.ConvertTimeFromUtc, which will allow for daylight saving time:

DateTime utc = DateTime.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);
Karl Gjertsen
  • 4,690
  • 8
  • 41
  • 64
  • What if my country's timezone is EEST in summer and EET in winter? How would that work with Daylight saving? – Rami Zebian Jul 23 '18 at 12:47
  • 1
    Windows knows the timezone information, along with daylight savings time dates. It should work it out or you if you choose one of the pre-defined time-zones. – Karl Gjertsen Jul 23 '18 at 12:49
  • 1
    This is the page I use to get the TimeZone IDs http://www.cryer.co.uk/brian/csharp/localisation_in_a_nutshell.htm#TimeZoneInfo.FindSystemTimeZoneById . Just be careful which ones you choose, for example "Central Standard Time" changes with daylight savings and is correct for say, Minnesota. But "Central America Standard Time" is for countries like Guatemala and they don't have daylight savings. – Matt Kemp Jul 06 '21 at 02:35
  • 5
    This doesn't seem to adjust correctly depending on daylight savings. – Rei Miyasaka Jul 25 '21 at 20:15
  • It adjusts correctly for daylight saving time for me. Make sure the date being converted falls within the daylight saving time range (the second Sunday in March to the first Sunday in November). Also check that the target time zone supports daylight saving time: `zone.SupportsDaylightSavingTime` should return `true`. – Eric Eskildsen Jul 28 '23 at 13:55
74

You need to get the UtcOffset from the TimeZoneInfo, then pass that to the ToOffset() method:

var dt = DateTime.UtcNow;
Console.WriteLine(dt.ToLocalTime());

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset)));
Paul Kearney - pk
  • 5,435
  • 26
  • 28
  • i see...you've got to get the UTC offset for that specific date in the timezone. thanks. – jaminto Jun 03 '10 at 19:50
  • 7
    This is not the best way compared to [Karl Gjertsen's answer](http://stackoverflow.com/a/16789973/57611) which uses a single .Net function to do the job instead of extracting the offset via creating a new, throw-away `DateTimeOffset`. – ErikE Jan 04 '17 at 00:32
12

Or better, if you don't want to hard code the time zone identifier:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
Pabinator
  • 1,601
  • 1
  • 21
  • 25
  • 4
    Couldn't you just use `TimeZoneInfo.Local` directly? Why do you need the call to `FindSystemTimeZoneById`? – CoderDennis Oct 14 '15 at 21:15
  • 4
    You are right, we don't need it. We can just do it like this `DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkDateTime, TimeZoneInfo.Local);` – Pabinator Oct 15 '15 at 15:40
  • 1
    But then you are fixed to a single time zone. Depends on how you want to use the code I guess. :-) – Karl Gjertsen Nov 05 '15 at 16:32
  • 17
    This is not very safe. If you are outsourcing your application to a cloud environment, you don't know which timezone is local per se. – Tom Jul 14 '16 at 08:24
6

I'm a beginner both at .NET and stackoverflow, so I could be wrong, but here goes:

Using TimeZoneInfo.ConvertTimeFromUtc will allow for daylight saving time, and convert to the correct time according to the time zone + a possible DST offset. However - the offset itself in the resulting object will show the offset for standard time, and not take daylight saving time into account. So if you want to do a ToString on the object, you will end up with the correct time (in hours and minutes), but the wrong offset during daylight saving time, which may lead to the wrong moment in time later in the code.

If you instead use the GetUtcOffset to get the offset for a specific time, and then do a ToOffset on the DateTimeOffset object, both the hours/minutes and the offset itself will be correctly converted, and you can safely do a ToString.

string ExpectedDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss''zzz";
string timeZoneId = "FLE Standard Time";
string dateTimestr = "2017-10-09T09:00:00+02:00";

DateTimeOffset dto = DateTimeOffset.Parse(dateTimeStr);
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
TimeSpan offset = zone.GetUtcOffset(dto);
dto = dto.ToOffset(offset);
string localTime = dto.ToString(ExpectedDateTimePattern);

localTime will return "2017-10-09T10:00:00+03:00".

Niels Pein
  • 61
  • 1
  • 4
  • According to the OP this is the correct answer. The main thing to understand is that UtcOffset for a timzone is not constant, instead it depends on the date itself what we are talking about *because of the daylight saving rules*. So the only mistake what the OP done is he used the constant BaseUtcOffset instead the GetUtcOffset(myDate) – g.pickardou May 22 '20 at 04:36
-1

This will Adjust automatically... and Return time as per your timezone.

public static string SetLastModified (

TimeZoneInfo csttzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZone.CurrentTimeZone.StandardName);

DateTime cstTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, csttzi);

return String.Format("DaylightSavingTime: {0}", cstTime.IsDaylightSavingTime().ToString());

}