在特定时区找到LocalDate的最后可能瞬间的最佳方法是什么?

Ben*_*son 9 c# nodatime

抱歉,如果这似乎是一个简单的问题,但我大多只想检查我所拥有的解决方案对于所有情况都是最明智/最有效的.

我们使用的预先存在的SQL Server数据库将'period'存储为包含start - >包含结束UTC DateTime值.(开始和结束列都会datetime2(7)自动转换为我们开始使用它们之前的System.DateTime实例DateTimeKind.UTC).

因此,如果我需要存储"整天/月/年,给定用户的时区",我需要找到"特定DateTimeZone中指定LocalDate的最后一个可能的瞬间".

我的方法如下:

public static LocalDateTime AtEndOfDay(this LocalDate localDate)
{
    return localDate
        .PlusDays(1)
        .AtMidnight()
        .PlusTicks(-1);
}

public static ZonedDateTime AtEndOfDay(this DateTimeZone zone, LocalDate localDate)
{
    return zone
        .AtStartOfDay(localDate.PlusDays(1))
        .Plus(Duration.FromTicks(-1));
}
Run Code Online (Sandbox Code Playgroud)

我想我还需要避免(在任何其他地方)映射"日期结束" LocalDateTime使用,.AtLeniently(..)因为如果23:59:59.9999999被"跳过"并且在目标中不存在DateTimeZone,那么它将被映射到下一个可用的瞬间缺口00:00:00.000000的'外侧',这将给我一个独家 ZonedDateTime价值.

修订方法:

public static LocalDateTime AtEndOfDay(this LocalDate localDate)
{
    // TODO: Replace with localDate.At(LocalTime.MaxValue) when NodaTime 2.0 is released.
    return localDate
        .PlusDays(1)
        .AtMidnight()
        .PlusTicks(-1);
}

public static ZonedDateTime AtEndOfDay(this DateTimeZone zone, LocalDate localDate)
{
    return zone
        .AtStartOfDay(localDate.PlusDays(1))
        .Plus(-Duration.Epsilon);
}

public static ZonedDateTime AtEndOfDayInZone(this LocalDate localDate, DateTimeZone zone)
{
    return zone.AtEndOfDay(localDate);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

首先,正如评论中所述,任何时候你可以使用独占上限,这将是一个好主意:)

你的AtEndOfDay方法看起来很合理,除了我用Duration.Epsilon而不是Duration.FromTicks.特别是,在Noda Time 2.0中,我们将转向精确到纳秒而不是刻度; Duration.Epsilon在这两种情况下都会做你想做的事.

对于您的LocalDate解决方案,在我看来,我们错过了LocalTime.MaxValue(或EndOfDay)的值,最大的可表示LocalTime.如果可以,你可以写:

return date.At(LocalTime.MaxValue);
Run Code Online (Sandbox Code Playgroud)

这将删除与以前相同的"滴答"问题.我会尽量记住将其添加到2.0中 - 尽管它会记录下来的评论"仅使用这个,如果你被旧系统强迫":)

添加一天然后减去刻度(或纳秒)的一个缺点是它会失败LocalDate.MaxValue.这可能不是一个实际问题,但对于Noda Time本身的代码,我们试图避免这样的事情.我不会试图为ZonedDateTime版本避免它,因为它是一个相当复杂的场景.(有可能这样做,但它不值得.)