56 comments

[ 4.8 ms ] story [ 111 ms ] thread
As the very last line mentions, "use UTC" and avoid silly DST issues like this.
And probably don't schedule anything for the last few seconds of a calendar year.
End of year is fine, it is around start of day / end of day when DST switches that screws up things
I was referring to leap seconds, which are applied at the end of the calendar in UTC, and are the only cases where UTC is not a continuous and predictable time scale. A scheduling system like cron still needs to have some mechanism to handle events that are scheduled in UTC, because particular UTC seconds can be skipped over. (And FYI, this can actually happen in other parts of the calendar year, not just the end.)
A leap second would be a change "less than 3 hours," so the job should still run according to the cited Debian man page.

Google's NTP servers smear leap seconds over an entire day, so UTC may appear continuous despite leap seconds.

https://developers.google.com/time/smear

Indeed. I only meant that simply switching to UTC doesn't actually reduce the necessity for the complex handling of scheduled events this article describes. It would just make these cases occur less frequently.
My shop opens when the local clock tower says 9 am

I want a cronjob set up to change the “closed” sigh to say “open”.

How do I set that with UTC?

Open your shop at 0900 UTC
Set the cron job to run every hour in UTC, and your application logic checks if its time to open in the configured time zone.
So the fix to using UTC for computers and crons that only care about the local time zone is to reimplement time checking?

If youre just gonna run it every hour, you might as well while(1){ check time; do stuff; sleep 1 hour;} now there's one less dependency?

It depends on that never dying.
You also depend on cron never having a bug, and you also depend on crons working as intended, unless you also have some extra system logging your cron jobs.
Unfortunately there’s more … interesting time zones than UTC+/-xx:00, and more interesting transitions than moving an hour.

For instance, Nepal uses UTC+05:45, and the time shifted by 15 minutes in 1986 (from UTC+05:30): https://www.timeanddate.com/time/zone/nepal/kathmandu

That said, I think running every 15 minutes handles all currently-observed time zones.

You store the time you want to see on the clock tower and the timezone where the clock tower is. Every hour you do the following pseudocode:

    if utc_now().to_timzone(my_timezone) >= "9AM":
        sign = "open"

I know you didn't mean this, but it was a problem I thought about: How does one make sure the local clock tower actually changes in cadence with DST? You can't, so I guess you could use open vz with a camera to have your open sign be based on what time is actually seen on the tower.

I know it's just an example, but I say in jest, don't use cron jobs to change your closed sign to open! If you can't make it to your shop, people will be waiting around all day for you to unlock the door. Very unhappy customers.

This is just duplicating the code already in cron. Of course you can make cron simpler by running your script every hour, and making the script more complex. You're just pushing the complexity to user-authored, non-reviewed, non-tested code. What is the advantage?
The first advantage is that you can dynamically check what your actual open hours are rather than having them statically configured (e.g. a web service to check for holidays). Open hours are never actually static. (Unless maybe cron does holidays?)

The second advantage is that you can check in multiple timezones especially if the server itself is in DST. Does cron itself let you set the timezone for each individual check? Or does it only run in one timezone? As far as I can tell, it only lets you use one timezone.

You can still run whatever business logic from cron to decide whether you took the day off or you have the resources to open. Offloading the timezone logic to cron still makes sense, since running tasks at the right time is exactly what it's for.
It's really about trading off something I understand fairly well (a script I wrote) and something I have questions about. Since it's not a particularly important problem and I'm more likely to make errors in cron, I'd rather have everything visible in a self-contained script.

For something important, I would look at it completely differently by testing it:

- What happens if I have a scheduled cronjob running every day at a certain time, but I want to override it for one specific day and have that job run later? (e.g. how is it accomplished so that I can maintain the default behavior while overriding and opening later on specific days)

- How can I make different commands run in different timezones? (as it stands now I find conflicting information about this)

- What happens if my machine lost power when the job needed to run? (it looks like it just never runs the script)

- Can I input a specific time and test if cron will set open for that specific time? (this doesn't seem possible)

some timezones go forwards/back 30 minutes with DST

and historically there have been even weirder cases

That’s a good point. It might make more sense to run it every minute or just have its own service if it’s that important. My use case is usually a user interacting with something that causes them to see something time specific.
This is a same problem in financial markets. Things like options contracts depend on a value observed say at 10am New York time on a particular date a decade in the future. If the daylight savings time schedule changes between now and then then the UTC time of the expiry of the options contract will change. The right reference isnt UTC or EST or EDT but "NY City local time" (or Tokyo or Warsaw or Mexico City or whatever is the relevant jurisidiction).
First of all, you’ll need a webcam pointed at the local clock tower…
Would that it were so simple! For cronjobs, maybe it often is, but DST transitions are a mess to deal with in things like calendaring UIs and other places where you have to convert point-in-time values to the format consumed by normal people, and where your users can have different but legitimate expectations about how those transitions should be handled.

At one company I remember helping build a scheduling UI for a linear TV broadcast channel, where you plan out the broadcast day in 24h blocks. Worked great except twice a year when, due to DST, you have either a 23h day or a 25h day, and half a dozen ways various customers expected that to be handled. The de facto solution was to have happy customers 363 days a year. :-/

Hey, but thank goodness for https://en.wikipedia.org/wiki/Uniform_Time_Act or it would have been even worse!

A better answer is to use time+locale for things that are supposed to happen in the future and UTC for things that happened in the past.

The reason is that things that happened in the past will have a specific moment on the arrow of time at which they happened, and UTC is as good as anything else for putting a consistent label on the arrow of time.

But, for things that are going to happen in the future, you have no way of knowing if two "time labels" that right now point to the same moment on the arrow of time might have some change that causes them to point to different moments. In this case UTC removes the ambiguity about the timezone that the time is in, but it adds ambiguity about which moment in time you're really talking about.

Let's say you want to schedule something for 9pm local time (UTC-3). So you schedule it for midnight UTC. Then your timezone shifts to UTC-2 and your appointment moves to 10pm. That's likely not at all what you intended. It's also why you need to pick a "master" timezone when you're sending invites to multiple timezones and let the rest of the times be derived from the "single source of truth" time.

This heuristic obviously doesn't work. I build a factory in a strategy game. It is going to take 10h. The timezone shifts; should it take longer, shorter, the same? Obviously the same.

You still need to use your brain and careful UI design. Things that a user scheduled to happen at a specific local time need to store the relevant timezone, implicitly or explicitly.

The key thing to realize about DST IMO, is the fact that time zone is adjusted for it.

So for example I live in Europe/Oslo, which is UTC+02 when DST is in effect (CEST). When DST is not in effect, my time zone becomes UTC+01 (CET).

And therefore, when we adjust our clocks, time is not really moved.

Although it may seem like the time turns back from 3 AM to 2 AM on 31 October 2021 in my location, that’s only true if you don’t take the time zone into account.

What actually happens is we go from:

2021-10-31T02:59:59.999…+0200

to:

2021-10-31T02:00:00.000…+0100

And we see then that if we convert this time to UTC, we have simply a transition from:

2021-10-31T00:59:59.999…Z

to:

2021-10-31T01:00:00.000…Z

So actually, nothing bad happened.

The article also says as much, but I wanted to comment on how I think about it when I consider DST, because I think it’s a pretty straight forward way to look at it.

Just to clarify the terminology, since you seem to be referring to the widely-used tz database, "time zone" is defined as a geographic region where local clocks agree year-round. Europe/Oslo is one such time zone in the tz database. Thus your time zone does not change when DST begins and ends, only your UTC offset.
Yes I may have formulated that part a bit clumsily. What I mean to convey is that the time zone changes between CEST and CET. And this in turn means different UTC offsets.

The Europe/Oslo identifier from the time zone databases was meant for context, but may have made what I tried to say less clear, sorry about that.

(Caveat that this may be US specific.) For the Central time zone there are 2 variants. CST and CDT. Most people will wrongly use CST to mean both variants but that is incorrect. Central Standard Time only applies when daylight savings is off and Central Daylight Time only applies when it is on.

The same is true for say PST and PDT.

CST and CDT are known as a single time zone, America/Chicago, in the tz database. The tz database can convert UTC times into local Chicago time. It even accommodates historic changes in DST law, like changes to the start date in prior years.
It's common to casually refer to "CST" and "CDT" as "time zones." I was only pointing out that in the specific context of the tz database, "time zone" has a specific definition that is distinct from individual UTC offsets.
Yeah. CST is a sloppy term; your computer is going to be America/Chicago or America/Indiana/Indianapolis (for the weird one that doesn't use DST), and those are unambiguous. (While researching this comment, I found that Indiana has at least 8 different time zones, so ... good luck with that.)

I don't know if you can type things like "CST" into Debian, but I don't think you can.

> (While researching this comment, I found that Indiana has at least 8 different time zones, so ... good luck with that.)

This is kind of the weakness with the IANA time zone classification. This defines time zones as the set of clocks that have shared the same time since 1970, so every time an Indiana county decided it wanted to move from Eastern to Central or vice versa, it got split into its own timezone. It reflects a level of precision that is perhaps greater than Indianans themselves actually keep.

[Also, FWIW, Indiana does observe DST now.]

> CST is a sloppy term;

It's not though, it means "Central Standard Time", which is UTC-06:00. It is sometimes sloppily misused to mean "Central Time", which is a sloppy term, meaning either UTC-06:00 (CST) or UTC-05:00 (CDT) depending on the time of year and where you are in the country.

> or America/Indiana/Indianapolis (for the weird one that doesn't use DST)

1. You mean `America/Indiana/Knox` or `America/Indiana/Tell_City` or historically almost any of the other `America/Indiana/…` zoneinfo files except for Indianapolis. Indianapolis has "always" (since 1961) been "Eastern" rather than "Central", it's other non-Indianapolis regions of Indiana that have been "Central, but without DST".

2. But regardless, it's outdated; all of Indiana has been doing DST since 2006; mostly Eastern (EDT/EST), but a few western parts of the state are Central (CDT/CST).

> (While researching this comment, I found that Indiana has at least 8 different time zones, so ... good luck with that.)

They only still exist for pre-2007 dates; for post-2007 dates they're all equivalent to either America/Chicago (…/Knox and …/Tell_City) or America/New_York (the other 6 of them).

> I don't know if you can type things like "CST" into Debian, but I don't think you can.

It's inconsistent. You can type in EST or MST, but not CST.

East Coast of Australia is similiar - normally we are AEST (Australian Eastern Standard Time), but during daylight savings, we are in AEDT (Australian Eastern Daylight Savings Time).
A taxonomy that's frustrating for a separate reason - the majority of the Australian east coast does not use DST.

(That's if you go by length of coast. If you go by population of states that do use DST, then, okay. If you go by number of states with a coast on the eastern side of the country that use DST, that's only 2/3, or 3/4 if you include Tasmania.)

Also I recently noticed that DuckDuckGo time zone conversion ignores you when you enter AEST and uses AEDT when the other states are in daylight savings time and yours is not.
Yeah, I was only referring to the Eastern states that do use DST at all. But thanks for pointing that out, although it might just have been clearer to say that Queensland does not use DST.
It seems pretty clear from the example that the commenter is using time zone to not mean entries from the tz database but instead offsets from UTC.
Huh, it's quite surprising to see the concurrent runs at 02:00 for multiple instances.

I guess this can cause quite a bit of weirdness if you use a spec like "5,17,32,47 * * * *" (to avoid the "thundering herd" of cronjobs at xx:00) and then getting four concurrent instances running at 02:00 in the daylight switchover hour?

The hour specifier in "5,17,32,47 * * * *" is "*", so this would count as a wildcard job, and Debian cron would not run it at xx:00. But, if the hour specifier started with anything but "*", that would be problematic. For example "5,17,32,47 0-23 * * *" appears equivalent, but Debian cron would run this one four times at xx:00 after a time jump.

Edit: I just ran the second example – https://gist.github.com/cuu508/7e42e5eecd42babf43f8d0dd0d987...

Interesting, thanks for running it. And yes I guess I got confused with the hour wildcard. So I guess the takeaway is to avoid non-wildcarded hours such as 0-23 or 0,1,2,3,4,5,6,7
DST must die. That's it. It's 21 century already. Why?
A lot of people (myself included) like it. Is that a rational reason? No, but it is a portent of how difficult it may be to get rid of it.
That's a perfectly rational reason! I like it, too.

Yeah, it makes it harder for programmers to accommodate. I'll play my violin for them next July when it's nice and bright outside at 7:30pm. :)

That might be a valid reason, but it's almost certainly not an explanation of why things are the way they are now or why they might change in the future. I don't recall there ever being a vote on the subject.
Because I don't like it getting light at 4am and dark at 5pm.
I'd prefer we stay on daylight time all year around, eliminate standard time. (Northeast US here.)
Because we live on an approximately spherical world whose rotation is not tidal locked to the star it orbits, that world rotates around an axis that is not perpendicular to its orbital plane around said star, we have a biology that uses sunrise to synchronize its internal clocks to the planet's rotation, we have spread to occupy regions of the world that are not near its equator, and we align our timekeeping to midnight or noon.
Because I enjoy having light in my morning in Winter, but allowing the extra hours of daylight to accumulate in the evening in summer.

The slight disconcertingness of the hour changes is worth it.

I hope nobody is depending on cron to be super reliable and accurate. If it matters how often a job is run, the job itself needs to account for it. Cron is simply not intended to be a super robust job scheduler.
The manual page is wrong. The UNIX clock is UTC, so DST transitions aren't a clock change, they're a local time discontinuity.

I'm pretty sure the article is wrong, too, because it implies that a DST transition won't cause cron jobs to be skipped or run twice. But it looks like the logic in Better-timeskip-handling.patch doesn't account for the possibility that the computer might be rebooted near a DST transition. Reboot immediately after the time falls back and it'll happily run the cron job a second time. The right way to handle this would have been to internally convert the crontab entries to UTC before scheduling them. It's surprising that OpenBSD (the origin of this patch) blundered this - usually they get the details right.

In what sense Unix clock is UTC? Unix clock is to a first approximation defined as number of second that have passed since a particular fixed point in time. As such, timezone considerations are pretty much immaterial to what Unix clock is.

This definition of Unix clock is only mostly correct, due to its treatment of leap seconds, but the way they are treated in Unix clock is not like how they are treated in UTC anyway (some Unix seconds last 2 SI seconds), so in this sense, Unix clock is not UTC either.

(comment deleted)