服务器上的ASP.NET时间转换(夏令时)

时间:2012-06-04 16:21:43

标签: c# asp.net sql-server-2008 dst

让我首先简要介绍一下我们的应用程序! (请不要立即关闭我的大帖子,它非常简单的场景,我只是描述性的!)我们有一个ASP.NET网站,主要是C#,作为我们所有商店的商店前端。专利权。

每个商店可能位于不同的时区,但我们需要在我们的网站上注明商店是开放还是关闭。

服务器有一个DB,其中包含指示不同商店的不同时间表的行,可以在我们的asp.net网站上显示。

在我的数据库中,我有列和行保存位置偏移量,并以UTC格式存储小时数。实施例;

  • 位置ID:21
  • TimeZoneOffSet:-5:00
  • SundayOpen:15:45
  • SundayClose:16:20

我想出了一种在服务器上确定位置是否打开的方法。我很难确定它是否适用于夏令时。我的问题是,这是否解释了夏令时,我是否正确地了解了这种情况,因为我没有像这样对时间有所了解?

这是我在服务器端代码中所做的事情;

//这是我用来保存来自数据库

的商店时间表的班级的重要部分
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;
}

感谢您抽出宝贵时间来查看我的解决方案!任何“单挑”或“禁忌”都会受到高度赞赏!

3 个答案:

答案 0 :(得分:2)

获得重构的自由。不是说我会做这样的事情,因为我可能会对数据库中的开放和关闭值进行非规范化,但是......这里是......

//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;  

}

答案 1 :(得分:1)

程序中的以下代码行正在处理时区并获取当地时间:

// 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);

但是,此代码仅处理添加时区偏移值而不处理DST的处理。

因此,如果您想获得DST,还有两种选择:

  1. 在数据库中为每个地方的夏令时期间使用一列,并做一个逻辑以查找该地区的当前日期是否在DST期间,并相应地在时间上进行DST更改。
  2. 如果您使用的是.NET 3.5及更高版本,则可以使用此选项:

    DateTime east = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.UtcNow,“Eastern Standard Time”);

    TimeZoneInfo类仅在.NET 3.5及更高版本中可用。

答案 2 :(得分:0)

一些建议和意见......


查看C#TimeZoneInfo类。 http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

它包含一些方法,可以使您的时区转换准确。例如,您可以存储TimeZoneId,而不是将TimeZoneOffset存储在数据库中。然后使用......

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(string id);

然后而不是..

locationTime = utcNow.Add(locationOffSetHour);  
你可以做......

 DateTime locationTime = ConvertTimeFromUtc(utcNow, tzi) ;

获取当地时间。这将为您提供更准确的偏移,因为它支持夏令时。

查看所有其他代码,看看TimeZoneInfo类是否包含您可以使用的属性和方法,而不是自己滚动。


您也不需要初始化值,然后立即覆盖它......

// 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...

您说您将数据库中的时间存储在UTC中。我假设您正在将此转换为本代码之外的某个地方,因为您正在执行此操作...

differenceCloseTimeSun = schedule.sundayClose - locationTime.TimeOfDay

您可以考虑对这两个值使用UTC时间,这样您就不必在计算差异之前进行转换。

您可能仍需要进行时区转换以确定星期几,但您无需进行转换以确定商店是开放还是关闭。


您实际上并未使用标准命名约定。不是必需的,但我会建议使用Microsoft标准作为起点。在StackOverflow上提问时,人们更容易阅读代码:)

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

希望这会对你有所帮助。