How to use TimeZoneInfo to get local time during Daylight Saving Time?
Asked Answered
E

6

99

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?

Eusebiaeusebio answered 2/6, 2010 at 21:45 Comment(2)
+1 - it drives me insane that TimeZoneInfo.ConvertTimeBySystemTimeZoneId doesn't Just Work for this :)Criseyde
@JamesManning - It does, assuming dt.Kind is set correctly.Humiliating
E
77

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)));
Eliga answered 2/6, 2010 at 22:15 Comment(2)
i see...you've got to get the UTC offset for that specific date in the timezone. thanks.Eusebiaeusebio
This is not the best way compared to Karl Gjertsen's answer which uses a single .Net function to do the job instead of extracting the offset via creating a new, throw-away DateTimeOffset.Pokpoke
C
81

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);
Canine answered 28/5, 2013 at 10:39 Comment(5)
What if my country's timezone is EEST in summer and EET in winter? How would that work with Daylight saving?Muntjac
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.Canine
This is the page I use to get the TimeZone IDs cryer.co.uk/brian/csharp/… . 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.Sheedy
This doesn't seem to adjust correctly depending on daylight savings.Maletta
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.Ajani
E
77

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)));
Eliga answered 2/6, 2010 at 22:15 Comment(2)
i see...you've got to get the UTC offset for that specific date in the timezone. thanks.Eusebiaeusebio
This is not the best way compared to Karl Gjertsen's answer which uses a single .Net function to do the job instead of extracting the offset via creating a new, throw-away DateTimeOffset.Pokpoke
S
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);
Salep answered 11/3, 2015 at 19:53 Comment(4)
Couldn't you just use TimeZoneInfo.Local directly? Why do you need the call to FindSystemTimeZoneById?Cockspur
You are right, we don't need it. We can just do it like this DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkDateTime, TimeZoneInfo.Local);Salep
But then you are fixed to a single time zone. Depends on how you want to use the code I guess. :-)Canine
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.Breakwater
D
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".

Delicate answered 7/11, 2017 at 12:3 Comment(1)
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)Gotama
J
0

I use the adjustment rules for the time zone:

TimeSpan ltz = TimeZoneInfo.Local.BaseUtcOffset;
foreach (TimeZoneInfo.AdjustmentRule ar in TimeZoneInfo.Local.GetAdjustmentRules())
{
    if (ar.DateStart < DateTime.Now && ar.DateEnd > DateTime.Now)
    {
        ltz += ar.DaylightDelta;
    }
}
Josettejosey answered 11/4, 2024 at 12:37 Comment(0)
E
-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());

}

Edgeworth answered 17/2, 2022 at 20:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.