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

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

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

因此,如果我需要存储“整天/月/年,给定用户的时区”,我需要找到“特定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)); } 

我想我还需要避免(在任何其他地方)使用.AtLeniently(..) )映射“日期结束” LocalDateTime因为如果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); } 

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

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

对于你的LocalDate解决方案,在我看来,我们缺少LocalTime.MaxValue (或EndOfDay )的值,这是最大的可表示的LocalTime 。 如果可以,你可以写:

 return date.At(LocalTime.MaxValue); 

这将删除与以前相同的“滴答”问题。 我会尽量记住将其添加到2.0中 – 尽管它会记录下来,对“只有你被旧系统强制使用时才使用它”的效果评论“:)

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