Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

determining the beginning of a day with timezones AND daylight saving

Tags:

c#

asp.net

I'm storing the user's timezone as a decimal in the session. For instance, if the user is in the EST timezone, I'd have

UserTimeZone = -5.00;

The data in the database is stored in UTC, so I want to calculate the beginning and the end of the day for that user so that when the user wants his data for a specific day, the records are timezone adjusted.

This is what I'm doing:

DateTime StartDate =  DateTime.Now.ToUniversalTime();

StartDate = StartDate.AddHours((double)UserTimeZone);
StartDate = StartDate.Date;
StartDate = StartDate.AddHours((double)UserTimeZone);

DateTime EndDate = StartDate.AddHours(24);

The problem I'm having is that this doesn't account for daylight saving time so even thought EST time is 5 hours behind UTC, for the moment it's actually 4 hours behind UTC because of the daylight saving shift.

What are some of your suggestions? Thanks.

like image 394
frenchie Avatar asked Sep 11 '11 23:09

frenchie


1 Answers

To make such calculations you will need to use the TimeZoneInfo and DateTimeOffset classes.

First of all, we need to get a TimeZoneInfo instance for both the local time and the user's local time:

var localTimezone = TimeZoneInfo.Local;
var userTimezone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

The caveat here is that you need to know the id of the user's local timezone (the offset that you currently have is not going to be enough). You can get a list of all TimeZoneInfo instances that the system recognizes with TimeZoneInfo.GetSystemTimeZones, and then you need a way of matching the user-provided timezone with one of those.

For this example, I have hardcoded EST.

Then you need to get a DateTimeOffset instance for today's midnight (start of day) in your local timezone:

var todayDate = DateTime.Today;
var todayLocal = new DateTimeOffset(todayDate,
                                    localTimezone.GetUtcOffset(todayDate));

Given this, you can calculate the DateTimeOffset instance that represents the midnight of "today" (based on your local time) in the user's timezone. Be aware that, depending on timezones, this may actually be in the future for the user's timezone!

var todayUser = TimeZoneInfo.ConvertTime(todayLocal, userTimezone);

And finally, you can create timestamps for both dates like this:

var epochStart = DateTime.Parse("01/01/1970 00:00:00");
var todayLocalTs = (todayLocal.Ticks - epochStart.Ticks)/TimeSpan.TicksPerSecond;
var todayUserTs = (todayUser.Ticks - epochStart.Ticks) / TimeSpan.TicksPerSecond;
like image 140
Jon Avatar answered Oct 21 '22 18:10

Jon