Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify a date in another timezone C#

I've got an asp.net application that must run some code every day at a specific time in the Eastern Time Zone (DST aware). So my first thought is, get the eastern time value and convert it to local server time.

So I need something like this:

var eastern = DateTime.Today.AddHours(17); // run at 5pm eastern
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(eastern, timeZoneInfo);
var local = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);

But how do I specify that the eastern DateTime object should be in the EST timezone.

Am I approaching this the wrong way?

like image 494
mikefrey Avatar asked Feb 09 '10 06:02

mikefrey


3 Answers

Seems I was able to answer my own question. Here's the code I'm using to get a next-run DateTime object.

    private DateTime GetNextRun()
    {

        var today = DateTime.Today;
        var runTime = new DateTime(today.Year, today.Month, today.Day, 17, 0, 0);
        var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
        var offset = timeZoneInfo.GetUtcOffset(runTime);
        var dto = new DateTimeOffset(runTime, offset);

        if (DateTime.Now > dto.LocalDateTime) 
            dto = dto.AddDays(1);

        return dto.LocalDateTime;
    }

Doing all the conversion using DateTimeOffset instead of DateTime proved effective. It even seems to handle Daylight Savings Time correctly.

like image 33
mikefrey Avatar answered Nov 07 '22 21:11

mikefrey


First, there are several things you have to consider. You have to deal with Daylight Savings Time, which from time to time seems to change (the start and end dates have changed twice in the last 10 years). So in the Northern Hemisphere Winter, Eastern time is -5 GMT (or UTC). But, in the Summer it's -6 GMT or is that -4 GMT, I can never keep it straight (nor should I have to).

There are some DNF library functions to deal with time zone information, however you really need .net 3.5 for the most useful stuff. There's the TimeZoneInfo class in .net 3.5.

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.Now,
     TimeZoneInfo.IsDaylightSavingsTime(tzi) ? 
        tzi.DaylightName : tzi.StandardName);
if (dt.Hour == 17)
    ....

Also, keep in mind that twice every year an hour is lost or gained, so you also have to account for that if, for example, you have a countdown timer you display "time until next processing" or something like that. The fact is, time handling is not as easy as it would seem at first thought, and there are a lot of edge cases.

like image 155
Erik Funkenbusch Avatar answered Nov 07 '22 21:11

Erik Funkenbusch


A DateTime doesn't know about a time zone. Even DateTimeOffset doesn't really know about a time zone - it knows about a UTC instant and an offset from that.

You can write your own struct which does have a TimeZoneInfo and a DateTime, but I'm not sure you need it in this case. Are you just trying to schedule 5pm in Eastern time, or is this actually more general? What are you doing with the DateTime (or whatever) afterwards? Using DateTimeOffset and TimeZoneInfo you can definitely get the UTC instant of the time you're interested in; if you just need to know the time between "now" and then, that's fairly easy.

I feel duty-bound to point out that when Noda Time is production-ready, it would almost certainly be the right answer :)

like image 4
Jon Skeet Avatar answered Nov 07 '22 20:11

Jon Skeet