UTC goes continuous on 20 May 2027
The General Conference on Weights and Measures met from 13 to 15 October and ended the leap second. Resolution 5: "continuous UTC will become effective on 20 May 2027". UTC may now drift up to 3,600 seconds from the Earth's rotation.
The last one is already behind us. IERS Bulletin C 72, dated 6 July 2026, rules out a leap second at the end of December. The next slot, end of June 2027, falls after the cut-off. The second added on 31 December 2016 was the final one.
What pushed it through was the risk of a first-ever negative leap second, put at 30% by 2035.
Good news for scheduled jobs. Mostly. Leap seconds were the rare, announced kind of clock jump. The common kind stays.
What leap seconds did to scheduled work
2012: timers that fired early
On 30 June 2012 the Linux kernel inserted a leap second without telling the hrtimer subsystem. In John Stultz's fix, posted 5 July, CLOCK_REALTIME timers fired a second early and sub-second ones fired immediately. Java and MySQL processes waiting on futexes spun at full CPU until someone reset the clock with date.
2017: a duration that went negative
Cloudflare's RRDNS timed resolver round trips by subtracting two time.Now() readings, and Go had no monotonic clock yet. At midnight UTC on 1 January 2017 the clock went back a second. A round trip came out negative, the smoothed average sank below zero, and rand.Int63n panicked on it.
Cron had nothing to do with either. Both times the culprit was code that trusted the wall clock to only move forward. Plenty of job scripts still do.
The clock steps that stay
NTP steps at boot
chrony fixes small errors by slewing the clock and steps the big ones. One of chrony's example configs and Debian's package both step with makestep 1 3: step if the clock is more than a second off during the first three updates. A host with a dead RTC battery can boot years wrong.
chrony logs its own steps and warns about jumps it didn't make:
journalctl -u chronyd -u chrony --since "-7 days" \
| grep -iE 'System clock was stepped|time jump detected'
Paused VMs and restored snapshots
A guest that was suspended or restored from a snapshot can come back with its clock behind. The correction is a forward step, sometimes of hours.
How cron reacts to a step
cronie wakes every minute and compares the wall clock with where it expected to be. cron.c sorts the difference into four cases:
forward 1-5 min run every missed minute, all jobs
forward 6 min-3 h wildcard jobs once, fixed-time jobs for each missed minute
backward up to 3 h wildcard jobs on the new clock, fixed-time jobs not repeated
more than 3 h treat as a correction: jump, replay nothing
It was written for daylight saving (see the DST post), but an NTP step takes the same path. After a 40-minute forward step a */5 job runs once and the seven runs in between are gone. Worse: a VM that resumes four hours behind and then steps forward loses every fixed-time job in those four hours. Nothing in the log says so.
A backward step of more than three hours resets cron's virtual time instead, and fixed-time jobs in the repeated span run again.
How systemd timers react
Calendar timers follow the wall clock
OnCalendar= timers are "realtime (i.e. wallclock) timers", and systemd.timer(5) warns they "might be triggered at unexpected times" on a clock that is set wrong. They are ordered after time-sync.target, which means little unless a wait service holds that target back. systemd-time-wait-sync.service does that for systemd-timesyncd, and its man page calls the chronyd fallback "not reliable". On chrony hosts use chrony-wait.service, which waits up to three minutes:
systemctl enable --now chrony-wait.service
Monotonic timers ignore the step
OnBootSec= and OnUnitActiveSec= run on CLOCK_MONOTONIC, which "is not affected by discontinuous jumps in the system time". A job six hours after its last run stays six hours apart through any step. Use them when the interval matters and the hour doesn't.
Run a unit when the clock jumps
OnClockChange=yes (systemd 242 and later) triggers a unit when CLOCK_REALTIME jumps relative to CLOCK_MONOTONIC. One small timer logs every step on every host:
# /etc/systemd/system/clock-jump.timer
[Timer]
OnClockChange=yes
[Install]
WantedBy=timers.target
# /etc/systemd/system/clock-jump.service
[Service]
Type=oneshot
ExecStart=/usr/bin/logger -p user.warning -t clock-jump "realtime clock jumped"
Measure durations on the monotonic clock
The shell version of the Cloudflare bug is a runtime computed from two date +%s calls. Across a step it comes out negative or hours long. In Python:
import logging
import time
wall_start, mono_start = time.time(), time.monotonic()
run_export()
wall = time.time() - wall_start
mono = time.monotonic() - mono_start
if abs(wall - mono) > 1:
logging.warning("wall clock moved %.1fs during the run", wall - mono)
Report mono as the duration. If the two numbers disagree, the clock moved mid-run.
Let something else keep time
Refuse to run on an unsynchronised clock
A job that picks yesterday's rows has no business running on an unchecked clock:
#!/bin/bash
set -euo pipefail
if [ "$(timedatectl show -p NTPSynchronized --value)" != "yes" ]; then
logger -t nightly-export "clock not synchronised, skipping run"
exit 1
fi
exec /usr/local/bin/nightly-export
Exit non-zero. A skipped run that exits 0 is a lie in your logs.
Check the schedule from another machine
A host can't tell that its clock lost four hours, since every timestamp it writes agrees with the wrong clock. A heartbeat monitor elsewhere judges arrivals by its own time, so a run that fires hours late, or never, shows up as missing. That is the dead man's switch argument, pointed at time itself.
Frequently asked questions about leap seconds and clock steps
When does UTC stop adding leap seconds? Resolution 5 of the 28th CGPM makes UTC continuous from 20 May 2027. IERS Bulletin C 72 already ruled out a leap second at the end of December 2026, so the one added on 31 December 2016 was the last.
Does cron run missed jobs after the clock jumps forward? cronie does for jumps of up to three hours: fixed-time jobs in the skipped minutes run, and wildcard jobs run once. A forward jump of more than three hours is treated as a correction, and the jobs scheduled inside it never run.
Can a clock step make a cron job run twice? On cronie, a backward step of up to three hours does not repeat fixed-time jobs, though wildcard jobs keep running on the new clock. A backward step of more than three hours resets cron's virtual time, so fixed-time jobs in the repeated span run again.
Are systemd timers affected by clock steps? OnCalendar timers use the wall clock, so a step changes when they fire. Monotonic settings such as OnBootSec and OnUnitActiveSec are not affected by jumps, and OnClockChange can trigger a unit whenever the realtime clock jumps.
How do I measure job duration safely across a clock step? Use a monotonic clock, such as time.monotonic in Python, instead of subtracting two wall-clock timestamps. A wall-clock difference can go negative when the clock is stepped, which is how Cloudflare's DNS failed on 1 January 2017.
Further reading
- Clocks Go Back on 25 October. Which of Your Jobs Run Twice?
- Monitoring systemd Timers: The Cron Successor Fails Just as Quietly
- Dead Man's Switch Monitoring: The Only Reliable Way to Watch Cron Jobs
Conclusion: Nobody will miss the leap second. The 2012 and 2017 outages came from code that used the wall clock as a stopwatch, though, and the next NTP step or resumed VM will find that same code in your crontab. Grep your job scripts for date +%s this week.
Sources: CGPM 2026 Resolution 5, IERS Bulletin C 72, Linux leap second hrtimer fix, SUSE: Leap second issues, June 30 2012, How and why the leap second affected Cloudflare DNS, chrony.conf(5), cronie cron.c, systemd.timer(5), systemd-time-wait-sync.service(8), clock_gettime(2).