.net – 比较Nodatime中不同时区的LocalDateTime

我正在开发一个允许用户安排活动的应用程序.用户通过使用 Time Zone Picker提供Olson时区,并通过asp日历选择器和第三方ajax时间选择器提供所述事件的日期和时间(因此提供的DateTime将始终采用相同的模式).我将用户想要的时间和用户提供的时区与服务器的时间和时区进行比较,并在用户期望触发事件的瞬间触发事件.

根据我的理解,阅读this link at the nodatime google group,将一个zoneddatetime转换为另一个时区(使用WithZone)是相当简单的(一旦我将用户的事件从LocalDateTime映射到zoneddatetime,显然).我不需要担心抵消,比如Pheonix和芝加哥之间的夏令时差异将得到恰当的考虑.

我最初将服务器的时间(DateTime.Now)转换为zoneddatetime并以此方式进行比较,但在阅读this link on SO之后,我切换到使用IClock.

到目前为止,在测试中一切正在发挥作用,但我担心我可能没有测试的极端情况.根据NodaTime的文档:

The biggest “gotcha” is converting LocalDateTime to zoneddatetime – it has some corner cases you need to consider.

我已经仔细阅读了文档,并且我认为这个问题涉及一年中那些不会发生或发生两次的时间.这些时间永远不会被设置为我们用户的事件时间,但我确实使用了LenientResolver.还有其他陷阱 – 当我从LocalDateTime转换为zoneddatetime时,我是否遗漏了任何东西,或者夏令时最终会困扰我?

另外,我需要在比较之前将用户zoneddatetime转换为服务器时区(我现在正在做)或者这是不必要的(甚至是错误的)步骤吗?如果我将事件的未转换zoneddatetime(而不是转换到服务器时区后的事件的zoneddatetime)与当前服务器zoneddatetime进行比较,NodaTime是否能够正确比较(没有夏令时问题)(参见下面的代码,第三行到最后一行)?当单步执行代码时,我可以看到时间和偏移量,但我担心这样做可能会导致问题过于简单化.

Protected Function EventIsReady(ByVal insTimeZone As String,ByVal eventDate As DateTime) As Boolean
        Dim clock As IClock = SystemClock.Instance
        Dim Now As Instant = clock.Now

        'server time zone (America/Chicago),unfortunately not UTC
        Dim zone = DateTimeZoneProviders.Tzdb("America/Chicago")
        Dim serverzoneddatetime = Now.InZone(zone)

        'user time zone
        Dim userTimeZone As NodaTime.DateTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull(insTimeZone)
        Dim userEventLocalDateTime = LocalDateTime.FromDateTime(eventDate)
        Dim eventzoneddatetime = userTimeZone.ResolveLocal(userEventLocalDateTime,Resolvers.LenientResolver)
        Dim eventTimeInServerTimeZone = eventzoneddatetime.WithZone(zone)

        Dim isReady As Boolean = False
        If eventTimeInServerTimeZone >= serverzoneddatetime Then
            isReady = True
        End If
        Return isReady
    End Function
听起来你走在正确的轨道上.

关于LenientResolver,请确保您了解其行为.它使用ReturnStartOfIntervalAfter作为弹跳间隙,使用ReturnLater作为后退重叠.

恕我直言,这不是安排未来事件的最佳配置. (见Issue #295),试试这个:

VB.NET

Public Shared ReadOnly SchedulingResolver As ZoneLocalmappingResolver = _
  Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier,_
  AddressOf ReturnForwardShifted)

Public Shared Function ReturnForwardShifted(local As LocalDateTime,_
  zone As DateTimeZone,before As ZoneInterval,after As ZoneInterval) _
  As zoneddatetime
    Dim newLocal As LocalDateTime = local.PlusTicks(after.Savings.Ticks)
    Return New zoneddatetime(newLocal,zone,after.WallOffset)
End Function

C#

public static readonly ZoneLocalmappingResolver SchedulingResolver =
  Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier,ReturnForwardShifted);

public static zoneddatetime ReturnForwardShifted(LocalDateTime local,DateTimeZone zone,ZoneInterval before,ZoneInterval after)
{
    LocalDateTime newLocal = local.PlusTicks(after.Savings.Ticks);
    return new zoneddatetime(newLocal,after.WallOffset);
}

关于服务器的时区 – 您应该将其从代码删除.您的代码不应该关心服务器的时区.相反,在zoneddatetime(您的eventzoneddatetime变量)上调用ToInstant(),然后将其与从clock.Now返回的Instant进行比较.

相关文章

Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强...
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办...
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace...
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用...
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选...
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As Dat...