2015-07-10 46 views
1

无论什么愚蠢的原因,我在处理时区时都很困惑。从SQL查询转换为基于TimeZoneInfo的本地时间的datetimeoffset

当创建一个记录,我用:

getutcdate() 

因此,例如,它是存储在一个DATETIMEOFFSET列,看起来像这样:

2015-07-03 20:44:21.0300000 +00:00 

所以没有偏移,只是原始UTC。

现在,在服务器代码中,我想要做一些事情......我有一个查询让我只是为特定用户发布的文章的CreatedDate。我在一个数据表存储这样的:

Dim tz as TimeZoneInfo = GetUserTZInfo(User) 
Dim dt as DataTable = GetArticleDates(User) 
Dim MaxArticles As Integer = 5 
Dim PostedThisMonth As Integer 
Dim Remaining As Integer 

我有限的用户元/月发表5篇文章,所以你可以看到,时间可以得到朝月的基础上,开始或结束摇摇欲坠用户的时区。这是明天的某个地方,然而到处都是同一时刻。

但我希望它是用户友好的,只是基于用户,而不是服务器时间。

我在上转换为本地时间,因为我DATETIMEOFFSET的数据类型的使用一些例子困难

任何人都可以提出关于如何实现以下最佳实践/方法:

  1. 搜索dt以查看与用户的月份相等的任何创建日期。
  2. 根据找到的内容为GeneratedMonth生成计数。

像我说的唯一的粘性区域是在月初或月底...基本上是12小时的窗口,当然是DST,但我不那么在意。

非常感谢帮助!

+0

只需使用日期数学,并根据用户时区进行调整。你有用户的时区吗? –

+0

@SeanLange我做的。我向你展示的示例函数为用户返回一个TimeZoneInfo对象。 – user1447679

+0

在数据库中这样做会更有意义吗?否则,你必须返回所有的信息,然后过滤它。只会首先返回你想要的数据会更有效率。 –

回答

2

恭喜你,你领先于大多数人。通过在数据库中存储UTC时间并使用TimeZoneInfo跟踪用户的时区,您就可以做到这一点。

如果你从来没有从+00偏离:00,你店JUSE一个datetimedatetime2代替datetimeoffset,但它不会伤害任何东西,所以它具有明确UTC的好处。

你真正需要做的是:

  • 使用用户的时区,以用户的本地每月的开始和结束转换为等效的UTC时间点发生。

  • 使用该值范围查询您的数据库。

    // compute the start of this month and the next month, by the user's time zone 
    Dim today As DateTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tz).Date 
    Dim startDateOfThisMonth As DateTime = New DateTime(today.Year, today.Month, 1) 
    Dim startDateOfNextMonth As DateTime = startDateOfThisMonth.AddMonths(1) 
    
    // convert those to UTC 
    Dim startUtc As DateTime = TimeZoneInfo.ConvertTimeToUtc(startDateOfThisMonth, tz) 
    Dim endUtc As DateTime = TimeZoneInfo.ConvertTimeToUtc(startDateOfNextMonth, tz) 
    

    或者,因为你在你的数据库使用datetimeoffset,你可以只建立在最后一步DateTimeOffset。扫描索引时,SQL将使用偏移量在内部转换为UTC。

    Dim start As DateTimeOffset = New DateTimeOffset(startDateOfThisMonth, 
                 tz.GetUtcOffset(startDateOfThisMonth)) 
    Dim end As DateTimeOffset = New DateTimeOffset(startDateOfNextMonth, 
                 tz.GetUtcOffset(startDateOfNextMonth)) 
    

当你查询你的数据库,使用table.dto >= @start AND table.dto < @end(一个半开区间)。

+0

非常酷和有趣的方法。感谢您的支持。现在就试试这个。我已经完成了所有的工作,但它仍然有点繁琐和昂贵。 – user1447679

+0

这真是太棒了......所以,为了完全清楚起见,如果我通过一个开始和/或结束的正面或负面的偏移量,SQL Server会照顾它吗?这似乎是工作,但只是想确定。非常感谢。 – user1447679

+0

如果你的字段是'datetimeoffset',并且你的查询参数也是'DateTimeOffset',那么是的 - 在查询过程中,SQL会将它标准化为UTC。否则,您将首先自己转换为UTC。如果你喜欢,你仍然可以自己做,或者你不信任SQL来做。 ;) –