Dates, Times, and User Intents
While almost any coding language you use has at least a data type for dates and times, they are still going to be frustrating to work with. This is even true if your framework of choice has numerous data types that are supposed to handle different situations. While the human mind can handle dates and times fairly well, there is a great deal of ambiguity in the way we express these things in language. This includes the way these things are discussed in planning. What makes this even worse is that you can often sound somewhat dumb when you ask for clarification around date and time issues, especially when talking to non-technical people. Because an intuitive understanding of time is very different from a technical one, almost any time (heh) that a date or time comes up, you really need to break things down further.
Besides getting clarification on user intent with respect to dates and times, each approach requires careful attention to your infrastructure, system design, and the quirks of various parts of your platform. With these factors in the mix, code that “looks right” can be dreadfully wrong, have oddball edge cases, or need to be overridden on occasion. Additionally, because dates and times are physical measurements, you also need to take variations in precision very carefully. You also need to be aware of things that may cause you to have to adjust dates and times in some instances (largely because people have schedules). Depending on the intent of the user, even two otherwise equivalent datetime values may need to be handled in vastly different manners.
Your users, and even different parts of your system, do not have the same view of time. A typical end user will want to see time expressed in their local time, as will a typical support person. However, if the support person is impersonating a user, they may be better off seeing the time in terms of the end user’s time instead of their own. Further, depending on the nature of your application, your end user might want to do different things when they are out of their normal timezone. System administrators and auditors will tend to want to view things in UTC time or in their local time, while external systems will likely either require UTC time, or will let you specify.
While in the past we’ve talked about dates and times from more of a data type understanding, it’s also important to understand how dates and times are expressed by users and different parts of a system. While dates and times are complex enough on their own, it gets even more complex once you take into account the way that people (and outside systems) may wish to interact with your system. Far from just recording all dates and times with a single datatype that serves all purposes. Rather, you are going to have to consider your user’s (or system’s) intent and then how you are likely to need to work with date-time information. It’s more than just knowing a bit about data types – you are actually going to have to really think through what the data types may imply about business logic if you want to do well here.
Just the date
You might need just the date for things like getting someone’s birthday, scheduling payments by day, or for things like scheduling a day off. The key thing here is that the date being requested by the user must be respected and NOT altered by the system to some other date. Time zones can play havoc with things here. You may not want to collect the date as a datetime at all, especially if it is not going to be used for scheduling. Birthdays are a good example of this.
If the date is used for sheduling, however, you will probably be better off to collect the day in the user’s timezone and then convert to your own for the scheduling purposes. You will want to display the date in the user’s default timezone when showing it to them, or when support is impersonating them. SysAdmins and external systems would need to see these dates in terms of their own timezones (or UTC). You will want to make sure this is consistent.
Just the time
In some cases, you may not be interested in the date at all, and only need to collect the time. A common use case for this is when you need to do something every day at a specific time. The key to this is that you don’t care about the date portion. When collecting this information from the user, you are probably best off setting the time on a date object, with the date set for today, and the adjusting to server time once the call goes server-side. If the server is the one dispatching the event, this ensures that it occurs at the correct time.
When displaying this to the user, you will once again need to convert to their local timezone. On the server side from a support perspective, you probably need to keep the user’s timezone in mind. If your support team can impersonate a user, they need to see things in the user’s timezone, not their own. Sysadmins and external systems will need to see these in either their local time or UTC time.
In this case, users are entering dates in a range. One or both dates may be nullable. This is often used to indicate that something only occurs during a particular date range (such as a hotel stay) without regards to the time. This doesn’t mean that other business rules don’t involve the time (such as checkout time). You’ll also see this in reporting.
You can generally treat both dates in this case in the same that you would treat other date-only input fields. This is the easy part. It gets more difficult when nulls are involved. A null start date on a date range can generally be understood to mean “starting now”, while a null end date can typically be understood to mean “forever”. This is important, because if the date is tied to something that costs money, you’ll get weird results with null start dates if you understand them to mean “to the beginning of time”.
You also need to be careful. When the user passes a date range in, you need to make it very clear whether the range is inclusive, that is, does it start on “StartDate”, or does it start AFTER “StartDate”.
Similar to date ranges, a user might select a range of times while filling in a form. This is probably less common than date ranges, but you still might find yourself using time ranges for things like scheduling shifts and the like. You are unlikely to see a case with a time range that is null on either end, nor are you likely to run into cases where the ends are non-inclusive.
You can generally treat both ends of the time input the same way that you would treat a single time input. While with time ranges you don’t have to worry much about inclusivitiy, you do have to worry about latency and transient system failures between parts of your system if the times are critical. For instance, if your business is contractually required to deliver something within a time range, RECORDING that time near the ends needs to be done carefully and with consideration towards latency.
You’ll also want to make sure that you always store the timezone with the times, especially if third parties are involved. At some point you are almost certain to have to try and track down why something stopped working across multiple environments, and this will help you avoid making incorrect assumptions that make things more difficult than they have to be.
Dates/Times (or spans) after an event or before a deadline
Sometimes, instead of expressing a when something occurs in an absolute sense, it’s better to express it relative to something else occurring. The critical date might be changed manually, and your users will expect the dates attached to it to change along with it. In this case, you have a couple interesting considerations. First, you need to store the offsets in terms of days, hours, minutes, etc.. However, you probably also need to pre-calculate the relevant dates and times, since you are probably going to be querying them.
You also have to be careful about validation here. When the critical date changes, any dates relative to that date will change, and could potentially change to something invalid. In design, you need to ask A LOT of questions about business rules when these types of conditions are in place. These can get extremely complicated, especially when things like contractual obligations, laws, and tax periods are in the mix. Be very careful.
Also, you’ll need to make sure that some resilience to disruption is built in when scheduling in this manner. It’s much easier to deliver something at 8:00, plus or minus two hours the day after a document is signed than it is to deliver the same thing at exactly 8:00. Business people often don’t think about this stuff until prompted to do so, so you’ll need to ask questions.
Recurring date schedules
You’ll also occasionally see situations where things are scheduled to occur on a particular day of the month, every month. Typically, the user will simply pick the numerical value of the date from a dropdown or other input. This can be interesting as well. For one thing, dates near the end of the month will require some business logic to handle appropriately, due to months having different lengths. Although you can just limit the date to 28th and no later, that may or may not work with your business rules.
If something being done on a particular day requires limited resources, you’ll also need to make sure that those resources are sufficient. For instance, if your users schedule a pest control visit on a particular day, you have to make sure that you have enough people to actually deliver on this on a particular day, and that other days are neither overloaded, nor slow, to the best of your ability (which will be limited).
Bear in mind that in the extreme, computing resources are also limited. With recurring date schedules, also consider what needs to happen if a day is missed. Does it need to be made up? If so, what is the logic for doing so? Or can it be skipped, and what needs to happen on the next event if so.
Weekday scheduling and other types of date scheduling
You may also see date/time inputs listed in a recurring manner based upon the day of the week, or some other oddball anchor point, such as the third Wednesday of the month. While computer systems and the people who build them have a preference for real dates and times, this is not always the case in the outside world.A good example of this might be a cleaning service that visits a client’s house on the first and third Tuesday of every month.
While the inputs for these may or may not be terribly complex, where this really gets fun and interesting is when you consider how you are going to store this data, both so that it can be later altered by the user and so that it can be available to the rest of the system, that is probably using absolute dates for scheduling.
As in the previous point, if you see one of these in a system that you are working on, it’s time to start asking a lot of clarifying questions, because the business logic required to support this effectively is going to be extensive. Depending on how the system allows the users to schedule things, you may also need to watch out for resource contention. This is especially true of systems that allow both absolute dates and dates relative to something else.
While users don’t typically enter timestamps, systems are expected to do so. Timestamps are especially important, because they often are used in regulatory compliance, system troubleshooting, audits, and support systems. They have to be accurate, and are often anything but…
Timestamps also have to be handled in a more holistic manner, due to the potential need to correlate them across broad swaths of one or more systems. This means you have to be careful about where they are taken (due to latency), when they are taken in a process (due to potentially needing to record multiple events in a consistent manner), and you need to watch how you record them so that issues such as timezones don’t present a problem.
Further, while your sysadmins will probably be content to view timestamps in terms of UTC, you should have no such expectation of auditors, regulatory agencies or (most) lawyers. While it’s great if they can handle it, it’s better if they don’t have to. As in previous cases, be aware of how timestamps are impacted by things like transient system failures, queues getting backed up, etc. Make sure that those events are visible based on timestamps if timestamps are required for regulatory purposes, or if you expect to use them as part of troubleshooting.
Real world event based
In some real world systems, you may also find that one component of any date/time that you enter is influenced by something outside the normal date and time considerations that you are used to. A good example of this might be things like tides, full moons, and holidays that are based on solar or lunar calendars. This includes things like calculating dusk, dawn, and the like. These are things which occur on a regular, predictable basis, but aren’t used much on calendars (except in places where they are often more critical than the regular calendar date). For instance, if your business is to provide various food items that are used on Passover Seder plates, more real world things (such as lunar cycles) are more critical to your success than the “regular” calendar.
When storing dates calculated in this manner, it is probably wise to use a well-maintained, third party calculator that is geared towards it, while storing the dates and times formatted to your “normal” calendar, so as to limit the confusion in the rest of the system. It may also be wise to store relevant dates and times in another table, so that you can cross compare to system events if it may be relevant. This isn’t so much because the dates you are storing are incorrect, but more because many of the people troubleshooting your systems will lack the relevant instinctive understanding.
Tricks of the Trade
When dealing with DateTime, it’s important to understand the intent of the user or the intent of the application you are building. This will guide you in how you are to build or design your code to work with a very abstract concept. Understanding intent though is its own abstract concept as it can be applied to more than just helping you know how to write your code. Knowing what motivates others or what they intend to will help you in any scenario. When dealing with business people, knowing their motivations and intents guides your explanations to them. They may not care that you can make the application x times faster, but may be extremely interested in the security of their data or vice versa. When interviewing for a job or dealing with management, understanding their intents and motivations will let you know how your performance will be measured and what you can do to look your best. Learn to read what motivates others and what intents they have.