Time arithmetic

Jul 09, 2026 Last reply: 9 hours ago 24 Replies

Email from a colleague claiming my "clock/time-of-day" software is broken.



As "proof", he offered up his (manual!) calculations and how they differed from results my code generates.



This, of course, because he has an incomplete understanding of "time". :< Or, has "forgotten" certain details in favor of a simpler mental model.



This all stems from the fact that we tend to do "time arithmetic" in our heads and gloss over idiosyncrasies that we (likely!) know about.



"This date next year is exactly one year from now." "This date next month is exactly 1 month from now." "This day-of-week NEXT week is exactly one week from now." "This time tomorrow is exactly 24 hours from now." "This 'minute' next hour is exactly one hour from now."



Nope.



These are only true if we use "squishy" definitions of time intervals.



If you're a person looking at a timepiece, such approximations may be acceptable. But, if you are an algorithm doing things at a certain *rate*, then you expect time to be incredibly uniform.



I think I can eliminate (most?) of these screwups by NOT allowing "human time" to be mapped to "system time" (a monotonically increasing counter that operates at a constant rate). So, instead of arranging for something to happen "an hour from now" by "incrementing the current hour" and using that as a scheduling criteria, take the current



*system* time and add 60 min * 60 sec to it and use that as the deadline.

Note that the "human time" corresponding to that could be confusing: 1:25:00 + 1 hour = 3:25:00 1:05:36 + 1 hour = 1:05:36 23:51:00 + 1 hour = 0:50:59 But, that only is confusing it *humans* want to read it. The machine (i.e., your algorithm) never is encumbered with such idiocy!



I think "non-programmers" might have a problem with this as they likely think "add 1 to the hour" to get a time one hour from now. But, I think they can learn to deal with it as: now = clock.now() alarm.set(now+HOUR)



So, as long as I don't let you map human time back to system time, you aren't likely to make mistakes with "time arithmetic".



But, that smells like it would cause other cognition problems...


OK, that all explains why I often get hungry before noon.

John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics

Don Y snipped-for-privacy@foo.invalid wrote: |---------------------------------------------------------------------| |"Note that the "human time" corresponding to that could be confusing:| |[. . .] | | 1:05:36 + 1 hour = 1:05:36" | |---------------------------------------------------------------------|

How could summing a value (e.g. "1:05:36") plus any value which is not zero (e.g. "1 hour") be equal to a value (e.g. "1:05:36" again)? (S.

formatting link
fuer Kontaktdaten!)

At 2:00 (AM), some places, here, switch between "daylight savings time" and "standard time" (and vice versa). I.e., at 2:00, the clock is rolled back to 1:00 (or forward to 3:00). This will happen in the wee hours of the morning.

So, on 1 Nov '26, there will be *two* instances of all times between 01:00:00 and 01:59:59 on that day (which of these "distinct points in time" do you mean when you refer to 01:05:36?)

The other example (1:25:00 + 1 hour = 3:25:00) occurred in the wee hours of 8 Mar '26 -- when the clock was advanced 1 hour at

2:00AM to read "3:00AM". I.e., the times 2:00:01 through 2:59:59 don't exist on that day. If you had an alarm clock, would the alarm have sounded AT ALL if set for 2:05:00? Should it sound at 3:00:00 as that is the first time >= the alarm time? Or, does the alarm just test for equivalence?

These things only have value to human observers. A machine sees 3600 seconds elapsing in each case.

The "design issue" is to create a solution that makes it difficult for people to make these mistakes. Just like it's impossible to take the sqrt of a negative value if you only allow "unsigneds" as the argument!

Don Y snipped-for-privacy@foo.invalid wrote: |------------------------------------------------------------------| |"At 2:00 (AM), some places, here, switch between "daylight savings| |time" and "standard time" (and vice versa). [. . .] | |[. . .]" | |------------------------------------------------------------------|

Good point.

|-------------------------------------------------------------------| |"The "design issue" is to create a solution that makes it difficult| |for people to make these mistakes." | |-------------------------------------------------------------------|

A good philosophy.

|------------------------------------------------------------------| |"Just like it's impossible to | |take the sqrt of a negative value if you only allow "unsigneds" | |as the argument!" | |------------------------------------------------------------------|

Many programs use signed variables for variables which are always supposed to be unsigned. E.g. if you get too much money in "Frontier: Elite 2" then you suddenly have minus a lot of money. (S.

formatting link
fuer Kontaktdaten!)

Similarly, the last "time" in 2016 Dec 16 was 23:59:60 -- which most software got wrong.

If you design strongly typed interfaces and keep this in mind, the user can't specify a "wrong" value.

E.g., using {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY} to represent day-of-week instead of some other arbitrary data-type (like [0..6] ... or should that be [1..7]??)

Don Y snipped-for-privacy@foo.invalid wrote: |----------------------------------------------------------------------------| |"If you design strongly typed interfaces and keep this | |in mind, the user can't specify a "wrong" value. | | | |E.g., using {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}| |to represent day-of-week instead of some other arbitrary data-type | |(like [0..6] ... or should that be [1..7]??)" | |----------------------------------------------------------------------------|

Indeed type Day_Name is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); is in Ada.Calendar.Formatting

Cf.

formatting link

(S.

formatting link
fuer Kontaktdaten!)

Yes, but imposing strong typing on languages that *aren't* strongly typed is a bit of a challenge.

And, programmers often silently rely on aspects of those encodings that aren't actually guaranteed:

SUNDAY (4) MONDAY (92) TUESDAY (8) WEDNESDAY (0) THURSDAY (662) FRIDAY (-33) SATURDAY (55)

will likely break code that relies on similarly named manifest constants.

Which one should come first -- Sunday or Monday? (Or even Saturday, in some parts of the world.)

Seems to me you want a representation that doesn’t presume a particular starting point for the week.

Exactly. If you want to encode a relationship in the dataset, then Mon > Sun > Sat > Fri > Thu > Wed > Tue > Mon > Sun ... (for some notion of ">" and a corresponding notion of "<")

I.e., there is no "start" of "a week" but, rather, an "ordering of days-of-the-week".

As such, they can't be expected to resolve to "(numeric) values" as the above relation wouldn't hold, numerically.

Yes and no. Questions like "What day is 3 days after Monday?" are still sensible. On the other hand, "Monday < Tuesday" might logically be false if it refers to Monday of next week.

"type Day_Number is mod 7;" could be a good fit, but the 'Succ attribute on enumerated types doesn't wrap around.

Defining Ada.Calendar.Formatting.Day_Name as an enumerated type is very convenient in some ways, but it doesn't *and can't* capture all the semantics of the days of the week. Any programmer using that package just has to be aware of that.

And the only operation provided in the package is the Day_of_Week function.

If you want more functionality, feel free to implement it.

Ideally, yes -- but such a type would be more difficult to use. Enumerated types are convenient. The choice of which day should be Day_Name'First can only be arbitrary.

Followups to comp.lang.ada; I don't think this has much to do with sci.electronics.

It belongs in (and originated in) SED as electronic *products* have to deal with time arithmetic (beyond just DoW issues) and have to address the needs and expectations of their users (computers tend not to care about days-of-week), regardless of implementation language.

My apologies for not noticing the change in newsgroup distributions and REMOVING c.l.a from my followup. Sadly, "Cóilín Nioclásín Glostéir" failed to extend the courtesy of alerting me to his change in distribution. If he wants to frolic in c.a.l he of course can freely do so.

I'll fix my news server to ignore such posts going forward.

I do not mean to be discourteous and I am sorry that I seemed to be discourteous. I often modify Newsgroups: headers and I do not hide Newsgroups: headers and I also often do not add a redundant "alerting" about evolving distributions. (S.

formatting link
fuer Kontaktdaten!

If you change the Newsgroup: header, please do mention it in the body of the message. It's not redundant. It's very easy for readers to miss the change (I'm not sure all newsreaders even show that header by default).

...

In Linux there is a date CLI program that is kept updated and does time calculation correctly for all countries, time zones, and dates. I don't know if there is a function that can be compiled in.

I assume this functionality is accessible in windows, at least using WSL

The mathematics of clock and days of the week come under the rubric of "clock arithmetic", which is a kind of modular arithmetic:

.

formatting link

Joe

The calculations are relatively straightforward (excepting future leap seconds; but, those may be going away...)

The problem is one of how we, as humans, think about time.

E.g., you think "a month from now" is "add 1 to current month, mod 12". And, for squishy definitions of "month", that's OK.

But, if you are "billed monthly" for something, chances are, it is ACTUALLY "every 30 days" (or maybe 31). So, the bill that arrives this month on the 15th may arrive next month on the 14th -- or 16th (or 13th, etc!)

As kids, we learn to do this "time arithmetic" so intuitively that we aren't even aware when we HAVE done it!

If I say I want something to happen "in 30 minutes", you *likely* assume 1800 seconds from now. *BUT*, you have no idea if that

30 minutes is an absolute interval or one DERIVED from my use of a local time reference: "Let's see... it's 8:30:00 now and I want to call Jesse at 9:00:00..."

Time references are plentiful. So, when I walk into my office, the REAL time (GPS-synced) may appear as 8:32:21 -- even though it didn't take me 2:21 to travel that distance!

So, in hindsight, that 30 minutes should have been something like

28 minutes... [If you've ever written a time service for an OS, you've encountered this when having to decide if you should bind relative times to the current time AT THE TIME OF SPECIFICATION or support free-running timers that only share the notion of "a second" with the other time services. And, you still have to address the interface to human time: what happens if the user sets the wall clock time forward by 19 minutes... will that 30 minute interval magically shrink to *11* minutes?]

The time zone data base isn't inside of the date program.

formatting link
Time Zone Database

The Time Zone Database (often called tz or zoneinfo) contains code and data that represent the history of local time for many representative locations around the globe. It is updated periodically to reflect changes made by political bodies to time zone boundaries, UTC offsets, and daylight-saving rules.

formatting link

hah, Don, had not heard from you in a while so I looked here (rarely do). And your thread reminded me to remind you that things can be even worse :). Many years ago (15? 20?) I was writing ntp for dps and, while reading plenty of related stuff I found out there were some correction seconds to be added/subtracted to each year. So a simple task became not so simple. I dug out some list of these seconds for many years back (don't remember how many) and got to work. Eventually I did it - may have taken me hours or even days. Guess what, the time I got like this was incorrect... Changing servers etc., same thing. Turned out the ntp servers were doing it before replying to me, I removed the lookup tables correction and I had the correct time :D.

====================================================== Dimiter Popoff, TGI

formatting link

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required