Hacker News new | ask | show | jobs
by bradleybuda 1589 days ago
The answer is no/no/no because you cannot define a general comparison operator between dates and times without additional context. It's possible that you can define a contextual comparison operator that works for your domain and the question you want to ask, but without knowing the application for this comparison it's pointless to try to make a general statement.

My mental model for these kinds of things is that Times are instants and Dates are either:

1. Ranges (with the start and end Time depending on TZ and possibly other context)

2. Discrete cells of a calendar (which are mostly TZ independent - July 5th doesn't happen at the same time everywhere, but it is well-defined everywhere)

Also, I've been writing code for 25 years and I still have no idea what a DateTime is.

6 comments

Isn’t DateTime fairly consistently just a singular moment it time, either absolute (TZ specified) or floating and therefore locale dependent?

Pretty sure these are the two cases which the python stdlib datetime covers.

1:30 AM on whatever date we "fall back" for DST isn't singular in my timezone
It depends on what you mean by timezones. 1:30am Pacific Time isn't well defined, but 1:30am PST and 1:30am PDT are.
Quick reminder that those timezone abbreviation are not unique (i.e. Philippine Standard Time)

https://www.timeanddate.com/time/zones/

Until daylight savings time ends and it's 1:30am twice. Time is hard.
Those two things are called the time zone - a geographical area that has and had the same time all the time - and the zone time within that time zone which might change from time to time, for example regularly because of daylight saving time or kind somewhat randomly because people change their mind about which time they want to use.
It’s not no, it’s undecidable. They are different types so there’s no equality operator defined.
So define one? Decide on something and you have a starting point for discussion.

The question is whether the definition is useful or not.

The problem isn't that you can't define an operator that will perform some boolean operation akin to equality on the values, the problem is that you can't define a universally agreed upon one. There's many sensible options (round to nearest, truncate, refuse entirely, and this is the start of the list not the end). The problem isn't a lack of options but an embarrassing surfeit of them. It's not that there aren't any answers, it's that there isn't an answer.

Moreover, there isn't anything intrinsically wrong with that. To go one "why" deeper, the problem is in the human brains that insist that such an operator simply must exist. How can we not do equality on times and dates? To which the answer is that your incredulity isn't really relevant and certainly doesn't create a universal answer.

Perhaps one "why" below that is a shallow understanding of operators in general, as Spivak references in a, err, nephew post of this one. If your concept of equality is that it was handed down from on high by your fourth grade teacher, you may have trouble dealing with the fact that there's really nothing special about it from a programming perspective, and programming routinely uses multiple concepts of "equality" even before we get into fundamentally ambiguous type comparisons! For instance, == vs. === in Javascript is two right there. Arguing about which is "the" equality operator is fundamentally flawed on the grounds that there really isn't such a privileged position of "the" equality operator to be occupied in the first place. We define many equality-like operators all the time, suitable for whatever local needs we have, and while there are certainly some that are more "equality-like" than others there is even so quite a few to chose from.

The ambiguity must be embraced and dealt with... or you will experience the implacable, impersonal engineer consequences of failing to do so, whatever those consequences may be for you in your particular situation.

Why define an operator? That is just asking for trouble. If you absolutely must compare two such values, insist that the person do the conversion manually at the comparison site, so that the intent and local use case is made explicit. Because you may wind up in a situation where someone else in the same codebase needs a different "method of coercion", and operator creation is fairly global-ish in most PLs.
You can define a type cast but it’s arbitrary.
If the date is, for example, the starting date of a contract, then the date is most likely just a shorthand for 00:00:00 on that date. With that there is no problem at all comparing the date with an instant and decide whether the instant is before or after the contract went into effect. This is not arbitrary, this is making explicit use of otherwise implicit domain knowledge.
All comparators are arbitrary, even among same-typed objects.

You can define a poset on the natural numbers ordered by divisibility that’s well defined and different from the usual < relation.

Pulling an example from maths, comparisons between integers and rationals are well defined despite them not being the same type. The obvious ordering uses the n <-> n/1 mapping but it doesn’t have to.

I would argue that both dates and datetimes dimensionally signify ranges of time with different lengths. A date being a range of ~24 hours and a time being a range of a minute/second/microsecond depending on the definition. It's rarely truly meant to signify an instantaneous point in time.

Looked at as ranges, equality can be defined as whether they overlap, and that works for most use cases but not all.

The only right model of dates and times is Java Time API. This is an example of great API design that everyone must be familiar with. For example, they have different representations of time there that are context-specific. Time is not always an instant and not always require a time zone: when you specify opening hours of a shop, they are defined as a LocalTime. ZonedDateTime is not the same as Instant in the context of calculations. Adding a day to instant always adds 24 hours. Adding a day to the time in the time zone observing DST may result in adding 23 or 25 hours. Time is not hard, it’s just you always need enough context to pick the right representation.
No. Date are the msb’s of time.
I wonder what kind of horrible design decision led to this in the first place.

I’d argue though, that without context, a date has the time 00:00 in your local time zone.

> I’d argue though, that without context, a date has the time 00:00 in your local time zone

I'd argue that without context a Date cannot have any time inferred. In the programming context it should be treated as a programming error and comparisons should fail to compile unless additional context is given.

A lot of the confusion here seems to stem from how we traditionally store dates (seconds/millis after a reference point in time), and over time we've confused the predominant way in which the data is represented from what the data actually is intended to mean.

    let date1 = Date("06/05/2022")
    let date2 = DateTime("06/05/2022 20:05 UTC")
    if date2 > date1 {
        // SHOULD NOT COMPILE
    }

    let date3 = Date("06/05/2022").withTime("05:00 UTC")
    if date2 > date3 {
        // DOES COMPILE
    }
Injecting context automatically without the intentional action/declaration of the programmer is where a billion bugs are born.
My guess is the UI uses dates but the database backend stores it as a time or unix timestamp.
But that would have been fine, they know the UI uses dates only. Even if you store as a time stamp you can pull out just the year, month day. Compare as normal.

These guys are comparing things that they know is a date only with something that needs a time stamp.

> Even if you store as a time stamp you can pull out just the year, month day.

In general, you need a timezone for that.