I'm currently writing a fairly simple app handling opening/closing times of businesses and running into serious difficulties trying to figure out how to properly store the info.
Most of our critical functionality is heavily dependent on getting times absolutely perfect, so obviously I want to get things done the best way possible to start off with!
Additionally, the data will be inputted by users, so if the underlying representation is slightly more complex (e.g. using TimeSpans to account for opening past midnight), this needs to be invisible to the user.
I need to store firstly, the business's opening hours, by day of week, with a timezone associated with them, e.g:
- M: 1000 - 2330
- T: 1000 - 0030
- W: 1900 - 0300
- Th: 2000 - 0300
- F: 2000 - 0800
- Sa: 1000 - 0500
- Su: 1000 - 2300
I'm currently thinking that the best way to store this is using a class like this:
public class OpeningHours
{
ZonedDateTime OpeningTime { get; set; }
Period durationOpen { get; set; }
// TODO: add a method to calculate ClosingTime as a ZonedDateTime
}
However, there's 2 main complications here:
I don't want to store the Year, Month, or Date part of the ZonedDateTime - I just care about the DayOfWeek.
Sure, I could just store each value as the first Monday/Tuesday etc after Jan 1 1970, but this seems hacky and pretty much plain wrong - as the author of NodaTime, very correctly, explains here when talking about the limitations of the BCL DateTime implementation. I also have a feeling this would probably end up with weird quirky bugs if later on we try and do any arithmetic with the dates.
Another thing I've considered is using a table with hours/days and letting people highlight the hours of the week to pick opening times, but you still run into the same problem with only wanting to store the DayOfWeek part of the OpeningTime.
Any suggestions would be appreciated, spending the last 6 hours reading about the hilariously silly ways we humans represent time has burnt me out a bit!
I would strongly consider using LocalTime
instead of ZonedDateTime
, for a couple of reasons:
So I would have something like this (showing just the data members; how you sort out the behaviour is a separate matter):
public class StoreOpeningPeriod
{
IsoDayOfWeek openingDayOfWeek;
LocalTime openingTime;
LocalTime closingTime;
}
Note that this exactly follows your original data as you've shown it, which is always a good sign - you're neither adding nor losing information, and it's presumably in a convenient form.
If the closing time is earlier than the opening time, it's assumed that this crossed midnight - you might want to add a confirmation box for the user if this is relatively uncommon, but it's certainly easy to spot and handle in code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With