Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I accurately represent a Date Range in NodaTime?

Tags:

c#

.net

nodatime

Goals

I have a list of LocalDate items that represent sets of start dates and end dates.

I would like to be able to store date ranges, so that I can perform operations on them as a set of overlapping or distinct ranges, etc.

Questions

  • Does NodaTime provide some sort of DateRange construct that I've missed in the docs?
  • Am I thinking about this wrong? Is there a more natural / preferred way to accomplish this that NodaTime already allows for?
  • Am I setting myself up for trouble by attempting to think about a date range using a LocalDate for a start and an end date?

I'm completely new to NodaTime and assuming that this is a conceptual misunderstanding on my part.

Update: I noticed a similar question on the subject from 2009, but that seems to refer to another utilies class; I'm assuming that since then NodaTime may have evolved to accomodate this situation.

like image 613
SeanKilleen Avatar asked Dec 15 '13 19:12

SeanKilleen


1 Answers

Noda Time provides an Interval type for a range of Instant values, but it doesn't provide range types for the other types. Part of the reason for this is the nuance of how ranges are used for different types.

If I give you a range of instants, it is always treated as a half open interval. The start value is included, but the end value is excluded. Humans do this naturally any time we provide a time value, such as when I say an event runs from 1:00 to 2:00, clearly I mean that the event is over at 2:00, so 2:00 is excluded.

But with whole calendar date ranges, typically the end dates are inclusive. To represent the entire month of January (as a range of LocalDate values), I would probably say Jan 1st through Jan 31st, and I am including the last day in its entirety.

We could probably add some additional range types to enforce these things, but we would need to think about how much value there is in having them in the API when you could probably just create them as needed. I'm not saying I'm for or against it either way, but that's probably something to be debated on the Noda Time user group.

To answer your specific questions:

  • No, there is no predefined range class for local dates.
  • The only other thing to consider is that calendar math is usually done via the Period class. For example, to determine how many days there are between two calendar dates:

    LocalDate ld1 = new LocalDate(2012, 1, 1);
    LocalDate ld2 = new LocalDate(2013, 12, 25);
    Period period = Period.Between(ld1, ld2, PeriodUnits.Days);
    long days = period.Days;
    
  • No, there's nothing wrong with creating a range class of local dates, there just might not be a whole lot of advantage. You may do just as well by having two properties, StartDate and EndDate, on your own classes. Just be careful about the inclusiveness of the end dates, vs the exclusiveness you'd see with an interval or time range.

And lastly, you said:

... so that I can perform operations on them as a set of overlapping or distinct ranges, etc.

You're probably looking for operations like intersection, union, calculating gaps, sorting, etc. These and more are defined by the Time Period Library, but Noda Time doesn't currently have anything like that. If one was to create it, it should probably be in a companion library ("NodaTime.Ranges", perhaps?). Likely it wouldn't be desired to pull it into the core, but you never know...

If you do end up using that Time Period Library, please make sure you recognize that it works with DateTime only, and is completely oblivious to DateTimeKind. So in order to be productive with it, you should probably make sure you are only working with UTC values, or "unspecified" calendar dates, and try not to ask it things like "how many hours are in a day" because it will get it wrong for days with daylight saving time transitions.

like image 104
Matt Johnson-Pint Avatar answered Oct 17 '22 00:10

Matt Johnson-Pint