抱歉,如果这似乎是一个简单的问题,但我大多只想检查我所拥有的解决方案对于所有情况都是最明智/最有效的.
我们使用的预先存在的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)
首先,正如评论中所述,任何时候你可以使用独占上限,这将是一个好主意:)
你的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版本避免它,因为它是一个相当复杂的场景.(有可能这样做,但它不值得.)