0

Let me start off by giving you all a brief run down of our application! (Please don't be instantly turned off by my large post, its quite simple scenario, I was just descriptive!) We have an ASP.NET web site, mostly C#, which acts as a store front for all of the stores within our franchise.

Each store could be in a different timezone, but we need to indicate on our site if the store is open or closed.

The server has a DB which hold rows that indicate different time schedule for different stores which could be presented with on our asp.net website.

In my database, I have columns and rows which hold the Location offset, and store hours in UTC. Example;

  • LocationID: 21
  • TimeZoneOffSet: -5:00
  • SundayOpen: 15:45
  • SundayClose: 16:20

I have come up with a way to determine on the server if the location is open or not. I am having a tough time determining if it will work with Daylight Savings Time. My question is, does this account for Daylight Savings Time, and have I gone about this scenario correctly, as I have not dealth with Time like this?

Here's what I do in my server side code;

//Here is the important parts of my class that I use to hold store schedule from the DB

public class TimeSchedule
{
    public TimeSpan locationOffset { get; set; }
    public TimeSpan sundayOpen { get; set; }
    public TimeSpan sundayClose { get; set; }

    public TimeSchedule()
    {
        locationOffset = new TimeSpan();
        sundayOpen = new TimeSpan();
        sundayClose = new TimeSpan();
    }

}

//I have loaded a TimeSchedule object by id
TimeSchedule schedule = location.getTimeScheduleByLocationID(21);

// Get the UTC time
DateTime utcNow = new DateTime();
utcNow = DateTime.UtcNow;

//Get the offset value that we stored in our schedule object
TimeSpan locationOffSetHour = schedule.locationOffset;

//I then apply the location offset hour to the server utc time.
DateTime locationTime = new DateTime();
locationTime = utcNow.Add(locationOffSetHour);

 // Get the day of the week from our locationTime that we off setted from UTC
 string LocationWeekDay = locationTime.DayOfWeek.ToString();

// Now for each case of week day, I check to see if the difference in time is >= 0
// If so I assume the store is open



 TimeSpan zeroDifference = new TimeSpan(0, 0, 0);


   // This switch case just gets the difference in time according to LocationTime (that we offset'd from UTC) and stored time for the location on the server.
   // Then verifies that the location is open for that day  
   switch (LocationWeekDay)
      {
          case "Sunday":
              // Verify that location is open, turn on open sign
              TimeSpan differenceOpenTimeSun = new TimeSpan();
              differenceOpenTimeSun = locationTime.TimeOfDay - schedule.sundayOpen;

          TimeSpan differenceCloseTimeSun = new TimeSpan();
          differenceCloseTimeSun = schedule.sundayClose - locationTime.TimeOfDay;

          if (differenceOpenTimeSun >= zeroDifference && differenceCloseTimeSun > zeroDifference)
           {

               imgSign.ImageUrl = "~/SiteImages/open.jpg";
            }
            else
            {
               imgSign.ImageUrl = "~/SiteImages/closed.jpg";
            }
            break;
}

Thank you for taking the time to look at my solution! Any "Heads-up" or "no-no's" would be greatly appreciated as well!

clamchoda
  • 4,411
  • 2
  • 36
  • 74

3 Answers3

2

Took the liberty to refactor. Not saying I would do everything exactly like this since I would probably denormalize the open and close values in the database but...here it is...

//I have loaded a TimeSchedule object by id 
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(schedule.LocationId); 

// Get the UTC time 
DateTime utcNow = DateTime.UtcNow; 

//I then apply the location offset hour to the server utc time. 
DateTime currentUtcTime = DateTime.UtcNow; 
DateTime locationTime = TimeZoneInfo.ConvertTimeFromUtc(currentUtcTime, tzi);

// Get the day of the week from our locationTime that we off setted from UTC 
string locationWeekDay = locationTime.DayOfWeek.ToString(); 

// Now for each case of week day, I check to see if the difference in time is >= 0 
// If so I assume the store is open 
TimeSpan zeroDifference = new TimeSpan(0, 0, 0); 

// This switch case just gets the difference in time according to LocationTime (that we offset'd from UTC) and stored time for the location on the server. 
// Then verifies that the location is open for that day   
switch (locationWeekDay) 
{ 
     case "Sunday":  
          // Verify that location is open, turn on open sign  
          TimeSpan differenceOpenTimeSun = currentUtcTime.TimeOfDay - schedule.sundayOpen;  
          TimeSpan differenceCloseTimeSun = schedule.sundayClose - currentUtcTime.TimeOfDay;  

          if (differenceOpenTimeSun >= zeroDifference && differenceCloseTimeSun > zeroDifference)  
           {  

           imgSign.ImageUrl = "~/SiteImages/open.jpg";  
        }  
        else  
        {  
           imgSign.ImageUrl = "~/SiteImages/closed.jpg";  
        }  
        break;  

}

Gene S
  • 2,735
  • 3
  • 25
  • 35
  • Thanks a bunch. The TimeZoneInfo class is exactly what I was looking for. I think .NET can probably handle DST better than myself. Although, schedule.LocationID is not the time zone, I think I will be able to tweak this to fit. Will update you after I get to try this out! – clamchoda Jun 13 '12 at 14:16
  • Sorry it took me so long to get back to this, I had a bunch on my plate. This was exactly what I was looking for, thanks. – clamchoda Jun 22 '12 at 14:15
1

The following lines of code in your program is handling the timezone and getting the local time:

// Get the UTC time
DateTime utcNow = new DateTime();
utcNow = DateTime.UtcNow;

//Get the offset value that we stored in our schedule object
TimeSpan locationOffSetHour = schedule.locationOffset;

//I then apply the location offset hour to the server utc time.
DateTime locationTime = new DateTime();
locationTime = utcNow.Add(locationOffSetHour);

But, this code is handling the adding the time zone offset value only and no where it is taking care of DST.

So if you want to get the DST also the there are two options for you:

  1. Use a column in the Database for each of the place's DST period and do a logic to get find whether the current date at that region is in DST period and do the DST changes in the time accordingly.
  2. This option can be followed if you are using .NET 3.5 and above:

    DateTime eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow, "Eastern Standard Time");

    TimeZoneInfo class is available only in .NET 3.5 onwards.

RinoTom
  • 2,278
  • 2
  • 26
  • 40
0

Some suggestions and comments...


Look at the C# TimeZoneInfo class. http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

It contains some methods that will make your timezone conversion for accurate. For example, instead of storing the TimeZoneOffset in the database you could store the TimeZoneId. Then use...

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(string id);

Then instead of ..

locationTime = utcNow.Add(locationOffSetHour);  

you can do...

 DateTime locationTime = ConvertTimeFromUtc(utcNow, tzi) ;

to get the local time. This will give you a more accurate offset since it supports Daylight Savings time.

Review all the other code and see if the TimeZoneInfo class contains properties and methods that you could use instead of rolling your own.


You also do not need to initialize a value and then immediately overwrite it...

// Change this...
DateTime utcNow = new DateTime();                
utcNow = DateTime.UtcNow;        

// to this...
DateTime utcNow = DateTime.UtcNow;        

// and this...
TimeSpan differenceOpenTimeSun = new TimeSpan();               
differenceOpenTimeSun = locationTime.TimeOfDay - schedule.sundayOpen;  

// to this...
TimeSpan differenceOpenTimeSun = locationTime.TimeOfDay - schedule.sundayOpen;  

// etc...

You say you are storing the time of day in UTC in the database. I am assuming you are converting that to local time somewhere outside this code since you are doing this...

differenceCloseTimeSun = schedule.sundayClose - locationTime.TimeOfDay

You might consider using UTC Time for both values so you do not have to do conversions before calculating the difference.

You probably still have to do the timezone convertion to determine the Day of the Week but you would not have to do the conversion to determine whether a store is open or close.


You are not really using Standard Naming Conventions. Not required but I would recommend Microsoft Standards as a starting point. Makes it easier for people to read code when asking questions on StackOverflow :)

http://msdn.microsoft.com/en-us/library/ff926074.aspx

Hope this helps you.

Gene S
  • 2,735
  • 3
  • 25
  • 35