在我的应用程序(Silverlight客户端 - 服务器 - SQL Server数据库)中,SQL Server作为后端,我需要在不同的时区进行各种计算和显示时间。我需要在客户端,服务器端和数据库端进行计算。
这是我需要同时使用各个时区的应用程序,它不是典型的“Local vs UTC” 所有数据都将以UTC格式存储,但我需要转换为: 1.地点时间 2.用户的时间
所以,让我们说如果我们谈论航空旅行 - 我将以UTC时间存储,但用户将在出发/到达时区看到它们。
我正在寻找最佳实践,如果我对如何接近它有错误,可能会纠正我:
DateTime
& TimeZoneInfo
功能困扰我的是,我将不得不在SQL Server和.NET上执行两组不同的功能来进行转换。我不想要SQL Server中的CLR代码。我很可能会在T-SQL中手动编写时间转换函数,我将让TimeZoneInfo在.NET端为我工作。
另外,我将不得不在DB中随处可见FK,我参考TImeZOne表。这将导致其他问题,如不断加入等。
您如何在数据库和应用程序中管理此类信息?
答案 0 :(得分:1)
正如djacobson所提到的,最好的办法是将转换从数据库中推出。将时间存储为数据库中的UTC。要求客户端进行时区转换,并且仅在UTC时间与服务器通信,以简化服务器的任务。如果服务器由于某种原因确实需要对时区进行日期识别,请让客户端或服务传递偏移参数以及DT参数,这样服务器就可以将其用作修饰符并仍然可以使用UTC时间。我想传递调整DT参数以使其达到UTC所需的分钟数,但只要您确保一致地处理请求,还有其他同样有效的方法。
这是我最近工作的项目的简化示例,该项目是针对移动设备的会议安排应用程序。 UTC -6中的客户请求从2011年11月20日开始的所有会议将通过MinutesToAdjustBy = 360
和StartDate = {11/16/2011}
。带宽要求规定服务器执行过滤。服务器应用程序将从此客户端的DB获取所有记录,然后通过选中record.MeetingDate.AddMinutes(MinutesToAdjustBy).Date == StartDate.Date
来过滤掉未命中。将所有通过此检查的记录返回给客户端,而不更改返回数据;即,MeetingDate
仍然是UTC。这避免了在转换为UTC或从UTC转换日历日期时的问题,并允许您的后端不知道实际时区。
顺便说一句,我的示例中的性能可以通过在所请求日期的任何一个方向上在1个日历日内查询所有StartDate
客户端记录的数据库来改进,以便显着减少记录数量取出。
编辑:我在最初的回答中误解了这个问题,并且对转换发生的位置问题感到困惑。我将离开上述内容,因为它与如何处理转换的问题相关,但它没有正确回答这个问题。
如果您愿意相信您的客户的系统将具有正确的(更重要的是,所有具有相同的)时区的注册表项并且将支持此方法,您可以存储并传递TimeZoneInfo.Id
对于出发和到达时区,并在客户端转换期间使用TimeZoneInfo.FindSystemTimeZoneById()
。它给客户带来了很多信任,但影响很小。
如果您愿意信任外部服务,您可以像上面那样对目的地和到达TZ ID进行类似的存储,然后调用服务客户端(或服务器端,如果绝对必要)来获取所需的服务信息。请参阅this question。
如果这些都不合适,那么您可能会陷入制作自己的时区表并将其缓存在您的服务中,正如您在问题中提到的那样。同样,在这里您可以遵循相同的基本设计:存储两个TZ ID,并让客户端从服务中获取所需的信息以便完成工作。