道歉,如果这似乎是一个简单的问题,但我大多只是想检查我所拥有的解决方案对于所有情况都是最明智/最有效的。
我们使用的预先存在的SQL Server数据库存储了一个'期间'作为包容性的开始 - >包含结束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));
}
我认为我还需要避免(在任何其他地方)映射"日期结束" 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);
}
答案 0 :(得分:5)
首先,正如评论中所述,只要你可以使用独占上限,这将是一个好主意:)
我的AtEndOfDay
方法看起来很合理,除了我使用Duration.Epsilon
代替Duration.FromTicks
。特别是,在Noda Time 2.0中,我们将转向精确到纳秒而不是刻度; Duration.Epsilon
会在两种情况下都做你想做的事。
对于LocalDate
解决方案,在我看来,我们错过了LocalTime.MaxValue
(或EndOfDay
)的值,这是最大的可表示LocalTime
。如果可以,你可以写:
return date.At(LocalTime.MaxValue);
会删除相同的" ticks"问题和以前一样。我会尝试记住将其添加到2.0中 - 尽管它会记录下来并对#34的效果进行评论;只有在您被旧系统强制使用时才会使用此功能。 :)
添加一天然后减去刻度(或纳秒)的一个缺点是它会在LocalDate.MaxValue
上失败。这可能不是实际问题,但对于Noda Time本身的代码,我们会尽量避免这样的事情。我不会试图为ZonedDateTime
版本避免它,因为它是一个相当复杂的场景。 (有可能这样做,但它不值得。)