I found sometimes, the outputs of,

last -x reboot
who -b
uptime -s
sudo journalctl --list-boots

Are showing different uptime since last booting which is annoying.

An example is,

last -x reboot
# wtmp begins Wed Apr  1 10:29:40 2020 <-- this is actually not a reboot time. Explain later
who -b
# system boot  2020-03-02 19:19
uptime -s
# 2020-03-02 19:19:54
sudo journalctl --list-boots
#  0 46e3eb28ab51489ab8eb236d65a5086f Mon 2020-04-13 10:51:31 PDT—Mon 2020-04-13 15:46:43 PDT

Although this might be a better solution which always tells us the truth,

systemctl status docker.service | grep since
# Active: active (running) since Thu 2020-04-02 15:56:23 PDT; 1 weeks 3 days ago

(Assuming dockerd shouldn’t be manually rebooted in a production environment. Any stable service should also do the job.)

Reasons

  1. system time is inaccurate (probably no hwclock, or out of sync)
  2. these commands are using the different data sources
  3. data sources were logrotate-ed (old part has been deleted/renamed)

The 1st one is easy to be determined.

last -x reboot

At system bootstrap an entry would be written to /var/log/wtmp with the username reboot, and at shutdown an entry would be written to /var/log/wtmp with the username shutdown.
Finding the times that the system was rebooted was a matter of using the last reboot and last shutdown commands to print out these entries.

Normally the output should be,

# shutdown system down  ... <-- first the system shuts down   
# reboot   system boot  ... <-- afterwards the system boots

Although under unexpected shutdown like hard power off,

# reboot   system boot  ... <-- then we've a boot WITHOUT a prior shutdown

Sometimes the last outputs only a part of info if there is too many login info. To find all the info, firstly find out all the wtmp logs by,

ls /var/log/wtmp*
# /var/log/wtmp  /var/log/wtmp.1

Then cat the old one,

last -f /var/log/wtmp.1 reboot shutdown
# reboot   system boot  4.15.0-88-generi Mon Mar  2 19:19   still running
# reboot   system boot  4.15.0-88-generi Mon Mar  2 19:14   still running

# wtmp.1 begins Mon Mar  2 15:50:57 2020 <-- this is just when the file begins

See, the output here matches the uptime -s and who -b in the first example.

who -b && uptime -s

Reads /var/run/utmp.

/run/utmp is a table of terminal login records, with special entries for bootup and shutdown. These entries are read by uptime and who -b. They are written by programs such as systemd-update-utmp, an analogue of the FreeBSD utx command, which are run as parts of the startup and shutdown procedures. They are not run first or last, as the relevant services are not (and indeed cannot be) ordered absolutely first or last. There may be journal entries with the relevant boot ID that precede the time that systemd-update-utmp reboot is run, and similar journal entries that postdate the time that systemd-update-utmp shutdown is run.

journalctl --list-boots

(In new systemd-journald), every journal record has a field named the boot ID. You can see this with the -o verbose option to journalctl. A boot ID is generated by the kernel at bootstrap, and systemd-journald applies the current boot ID, taken from the kernel, to every log record as it is adding it to the journal.

To implement the list-boots functionality, journalctl scans the entire journal, reading the timestamps and boot IDs of every record, and noting the earliest and latest timestamps associated with each unique boot ID.

Thus if parts of the journal are purged, or conversely stick around overlong, the apparent boot and shutdown times reported by journalctl will differ wildly from the actual boot and shutdown times.

In sum, the journald logs usually get purged (logrotate-ed). So it’s not reliable.

Conclusion

Always use uptime [-s].

Refs.