How to set a ZonedDateTime's time component in Nodatime correctly

I have a method that is supposed to return the start time of a working day, e.g. 9AM from a ZonedDateTime that it takes as a parameter:

public ZonedDateTime GetWorkStartTime(ZonedDateTime zdt) => (zdt.Zone.AtStartOfDay(zdt.Date).Date + WorkDayStartTime).InZone(zdt.Zone, CommonLenientResolver);

WorkDayStartTime is a new LocalTime(9, 0)

CommonLenientResolver is a custom resolver, see the implementation at Comparing LocalDateTime for Different Time Zones in Nodatime

So for any particular zdt, I'd like to be sure that the return value is always the 9AM of the day that the zdt parameter represents.

As stated in AtStartOfDay(...)'s documentation, should the midnight of a day where the clock changes not exist (e.g. the clock moves forward at midnight straight to 1AM), Nodatime will automatically use the next available instance, 1AM. In my current implementation, I'm adding 9 hours to AtStartOfDay(...), therefore if the start of the day is ever 1AM, my GetWorkStartTime(...) will return 10AM, which is what I'd like to avoid.

I'm using Nodatime 1.3.1.

Jon Skeet
people
quotationmark

It sounds like you don't need to use AtStartOfDay at all - just use the date and add your WorkDayStartTime:

public ZonedDateTime GetWorkStartTime(ZonedDateTime zdt) =>
    (zdt.Date + WorkDayStartTime).InZone(zdt.Zone, CommonLenientResolver);

Or if you find it clearer:

public ZonedDateTime GetWorkStartTime(ZonedDateTime zdt) =>
    zdt.Date.At(WorkDayStartTime).InZone(zdt.Zone, CommonLenientResolver);

Assuming your resolver handles everything the way you want it to for skipped/ambiguous values, that should be fine.

people

See more on this question at Stackoverflow