The pre-existing SQL Server database we work with stores a 'period' as inclusive start -> inclusive end UTC DateTime values. (Both start & end columns are datetime2(7)
, automatically-converted to System.DateTime
instances of DateTimeKind.UTC
before we start working with them).
So, if I need to store the "whole day/month/year, given the user's time-zone" I need to find "The last possible instant of a specified LocalDate, in a particular DateTimeZone".
The methods I have are as follows:
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));
}
I think I also need to avoid (anywhere else) mapping a "end of date" LocalDateTime
using .AtLeniently(..)
since if 23:59:59.9999999 is "skipped" and does not exist in the target DateTimeZone
, then it would be mapped to the next available instant on the 'outer' side of the gap 00:00:00.000000, which would give me an exclusive ZonedDateTime
value.
Amended Methods:
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);
}