221 comments

[ 3.7 ms ] story [ 243 ms ] thread
Also, time is unidirectional.
Well time would be unidirectional, right?

The computer clock might not be.

Ooooh, nerd time!

If you are moving faster than the speed of light, you are perceiving whatever you are moving away from in reverse, because the light you are seeing was generated before when you left. (you are passing into light that is older than the light you started with). In terms of space-time, you would then be going backwards in time, if your point of reference for time was the Earth (and hint, given that we have all these nuanced time thingamajigs, it is)

If you are moving faster than the speed of light, our understanding of physics is wrong and we can't make any sensible predictions.
I think this would be better stated as, "the system clock increases monotonically".
Can someone explain #1? I suspect it has to do with crossing time zones?
Day light savings transition days. When you skip ahead, that day has 23 hours in it. When you fall back, it has 25.
Also, any other change to the system clock. NTP will either slew or step the system clock to keep it synchronized with the upstream time source. And the user can explicitly set the clock, as well. See also assumptions 9 and 10.
(comment deleted)
(comment deleted)
What moskie explained, but got me thinking - if somehow your laptop always synchronizes with the current zone, and you are in a airplane flying east->west, or west->east?
Who believes these things? February is always 28 days long? Any 24-hour period will always begin and end in the same day (or week, or month)? A week always begins and ends in the same month?
He's talking about test code. So if those test cases are missing, but the programmer thinks the tests are thorough, then it looks like the programmer believes those things (or forgot that they weren't true).
A bad test might boil down to,

    assert(month(now()) == month(now() + 24.hours))
then fail from time to time.
I thought about the same thing. I choose to read the title as "Falsehoods programmers seem to believe about time". Or "act as if they believe" in place of "seem to believe".

I can easily imagine somebody introducing a bug that relies on a 24 hour period ending in the same month as it began.

Perhaps the accurate title is "Assumptions programmers make about time"
Bugs happen. Especially thoughtless ones.

The title might better have been "Things programmers have tried to do with time."

About #7: doesn't a month always end in the same year it started?
Well I guess it is possible if you used some Chinese or Jewish calendar or something like that.

But at least in the western system it shouldn't be possible to it to span years.

The way you're thinking about it, yes -- but the passage of a month may take you from December the [mumbleth] to January the [mumbleth], which are in different years. For some strange reason, code in the wild doesn't always account for that, so the due date for an item may well be eleven months before the request was entered.
I like to call this kind of bug "New Year's Wake-up Call from Hell".
One I caught recently: The difference between the current time and one week from the current time is not always 7 * 86400 seconds.

By noticing an automated test that failed 2 weeks out of the year.

I think every test suite has tests that only fail right around the start and end of daylight savings time.
If the tests are failing because the production code is confused about daylight savings time, then you may have a serious problem.

If on the other hand it's just the test code that's flaky, usually such problems can be alleviated by refactoring such that one passes the time function as a parameter. This is in preference to hard-coding calls to the system time in test, which imho one should never do.

Once an arbitrary time function can be passed as a parameter, one can provide a mock or fake system clock for test purposes. Ideally one would still want to test under daylight savings' conditions. But at the least this approach leaves one in a place where one can test the common 24-hours-in-a-day case without having the tests spuriously fail two days out of every year.

Between 1582 and 1752 England had two different New Year's Days, January 1 and March 25, used for different purposes. The same day had different years depending on who you were talking to. See http://en.wikipedia.org/wiki/Dual_dating.
The tax year in UK still start/end on March 25th IIRC
6th April, actually.
Ah yes that sounds more reasonable. I knew it was around that date.
One of my favorites, encountered in the wild: Your system will never need to handle a time before 1970.
Ran into a similar one about ten years ago; a medical records system with the assumption that you wouldn't need dates before 1/1/1900.

You know who goes to the doctor a lot? Centegenarians.

35. Two timezones that differ, will differ by an integer number of hours.
36. Two timezones that differ will differ by an integer number of half hours.

37. Okay, quarter hours.

38. Okay, seconds, but it will be a consistent difference if we ignore DST.

39. If you create two date objects right beside each other, they'll represent the same time. (a fantastic Heisenbug generator)

40. You can wait for the clock to reach exactly HH:MM:SS by sampling once a second.

I'm not sure this counts as a constructive comment, but an interesting anecdote anyway - an early coding partner of mine once wrote a procedure he expected to run once exactly every second by continuously polling the time in a while/do_nothing loop until exactly one second had passed. It took some convincing to get him to accept that try as he might, it was very unlikely that "==" was what he wanted there.

The best part was that this was in Javascript (and obviously he was not using a timeout). The entire page would lock up while it waited for the second to elapse. He never even figured out the obvious usability concern because he was so confounded by the fact that the procedure wasn't getting called after a second had passed.

Ok, to be fair, it was a freshman year programming class - not an unexpected or even unusual mistake. But it gave me a chuckle just now remembering it.

Somewhat related, but I've seen a lot of retry-with-a-timeout loops that will either throw a spurious timeout error or wait for a very long time if the system clock just happens to jump at the right time.

Another amusing anecdote: I got an old PowerBook out of storage and booted it up. The battery had run flat, so the clock reset to 1970. Spotlight noticed this and decided it had to reindex the entire drive. At some point during all of this, NTP kicked in and reset the clock to the correct year. I wanted to see how long Spotlight would take to finish indexing, so I popped down the menu. The progress bar indicated that it was about halfway done, and based on how long it had taken so far, it estimated that only another 40 years would be required to finish!

In the same vein I can bet I have seen at last 5 implementation of date diffing using string representation.
#40 actually made me laugh out loud. Bitterly, but out loud :-)
What has a non-integral number of seconds?

I just found out today about Calcutta time, which until 1948 was GMT+05:30:21, but I didn’t realize it could be even worse than that.

Yeah, that one even made it into the EXIF standard...
N. The offsets between two time zones will remain constant.

N+1. OK, historical oddities aside, the offsets between two time zones won't change in the future.

N+2. Changes in the offsets between time zones will occur with plenty of advance notice.

N+3. Daylight savings time happens at the same time every year.

N+4. Daylight savings time happens at the same time in every time zone.

N+5. Daylight savings time always adjusts by an hour.

N+6. Months have either 28, 29, 30, or 31 days.

N+7. The day of the month always advances contiguously from N to either N+1 or 1, with no discontinuities.

Explanations:

(N)-(N+2): There exist enough jurisdictions in the world that time zone changes occur often enough to require regular updates to the time zone database, more frequently than many distribution release schedules occur.

(N+3)-(N+5): Jurisdictions change DST policies even more frequently than they change time zones.

(N+6)-(N+7): September 1752 had 19 days: 1, 2, 14, 15, ..., 29, 30.

> September 1752 had 19 days: 1, 2, 14, 15, ..., 29, 30.

In the British Empire, anyway.

From which many modern reckonings of time descend, including the one used by all modern computer systems.
Actually, almost no country outside the British Empire (and not even Scotland inside it) implemented the Gregorian reform at the same time. Britain was pretty late in doing so, too.

As for "all modern computer systems", Unix time is completely ignorant about anything except seconds.

> Unix time is completely ignorant about anything except seconds.

In hindsight, it seems like a brilliant decision.

But then we had to go and make it care about leap seconds...
Except it doesn't account for leap seconds.
Is that true? Isn't that the responsibility of the whatever component that translates the number of seconds since Jan 1 1970 into a calendar?
Unix time is not the number of seconds since Jan 1st 1970.
> Unix time is completely ignorant about anything except seconds

That's not correct, actually: UNIX time tracks UTC instead of TAI meaning it "corrects" for leap seconds. As a result, UNIX time is not "the number of seconds since epoch" but "86400 * (number of whole days since epoch) + (number of seconds since midnight)", and UNIX time will go forwards (never so far) and backwards on leap seconds (a second will repeat in most implementations as the day goes from 23:59:60 to 00:00:00, as they have the same timestamp).

Corrollary: The same month has the same number of days in it everywhere!
My favorite eye-stabby example of this was parsing RSS feeds (with meaningless timezone abbreviations!) from sites in the southern hemisphere. Depending on the date and various last-minute laws (thank you, President Chavez), the differential would be 0, +1, +2, +2.5 or +3 hours between various points.
> September 1752 had 19 days: 1, 2, 14, 15, ..., 29, 30.

That's only in the British Empire. Other countries moved to the Gregorian Calendar at different times. It began being adopted on 15 October 1582 (the day after 4 October 1582) in some Roman Catholic countries (Spain, Portugal, Italy, Poland). Russia didn't switch until 1918.

So, you could also have:

N+8. There is only one calendar system in use at one time.

And the list hasn't actually covered the Gregorian calendar at all, since many people may not know the actual leap year rule.

N+9. There is a leap year every year divisible by 4.

The actual rule is that there is a leap year every year divisible by 4, except those divisible by 100, with a further exception to that exception for years divisible by 400, (so there is a leap year on such years). The year 2000 is one such year divisible by 400, so we have not yet passed a year divisible by 4 which is not a leap year since the invention of computers.

N+9.1: Non leap years will never contain a leap day.

http://support.microsoft.com/kb/214326

But that's a bug in Excel. "Non leap years will never contain a leap day" is true.
It was a bug in Lotus 1-2-3 that was intentionally implemented into Excel, so technically it was a backwards-compatibility "feature". And some items from the original list aren't exactly "truths" as much as implementations or configurations, e.g.

> 19. The system clock will never be set to a time that is in the distant past or the far future.

> 20. Time has no beginning and no end.

'items from the original list aren't exactly "truths" as much as implementations or configurations' QFT.
N+8. It will be easy to calculate the duration of x number of hours and minutes from a particular point in time.

The reason this is impossible on Windows and downright awkward on Unix is because DST changes from time to time. Unless you have something like tzinfo, you cannot work out a particular date and time by merely adding a duration to another date and time in the past.

Instead, you must work out the timezone you are doing the calculation in, then work out whether the duration needs to incorporate a DST change, which involves working out what that DST changeover date and time was...

Of course, it's impossible on Windows because Microsoft only give the start and end datetime offsets for the current year. Amazingly, after all the patches they've had to issue to fix DST changes over the years, they still haven't implemented a Windows equivalent of tzinfo yet. And may never do so, even though they really aught to, given they are one of the leaders in calendaring software.

This was hilarious for people who had booked tickets on flights out on the 30th. Do you leave on the 29th or the 31st...? This was a real problem for the airlines and headache for a number of travellers.
Hmm. I've written code which assumes that Monday is two days after Saturday and one day after Sunday.
36: Continguous timezones are no more than an hour apart. (aka we don't need to test what happens to the avionics when you fly over the International Date Line)
Sometimes time is simplified on purpose:

  15.9.1.2 Day Number and Time within Day # Ⓣ
  
  A given time value t belongs to day number
    Day(t) = floor(t / msPerDay)
  where the number of milliseconds per day is
    msPerDay = 86400000
http://es5.github.com/#x15.9.1.2
36. GMT and UTC are the same timezone.
36b. Britain uses GMT. Not true, we use BST (British Summer Time) during the summer.
If you really want to stress test time handling code, try to get it to accept Feburary 29, 1900 and Feburary 29, 2000. The first doesn't exist but the second does.

But really, with regards to time use whatever library came with you programming language.

That will stress it a bit, but to really torture it, see if it accepts 2012 June 30 23:59:60
Well, you don't know if 31.12.2015 will have a 23:59:60 or no. These seconds are announced just prior to being added, the system couln't possibly know it.
Obviously no.

That's after the Mayapocolypse.

35. There are years past 2079. SQL Server smalldatetime only goes up to June 6, 2079
Checking the terminal, I don't see any corporate bonds maturing in 2079 yet. But I do see a handful in every year >= 2070 and <= 2077. So maybe a few more years and some people / firms will start hitting bugs...
And it doesn't even mention all the bizarre things that have been done (for reasons good and bad) to time by various governments. Like adjusting from local solar time to standard GMT offset timezones (which involves skipping a given number of minutes and seconds or having them twice). Or introducing/abolishing/moving around daylight savings time. Or "super daylight savings time" with a 2 hour offset. Or moving from one side of the international date line to the other. And of course the real biggie: the Gregorian calendar reform that various countries adopted at different times between 1582 and the 1920s, skipping between 10 and 13 days depending on when they adopted it.
My favorite is when Daylight Savings Time started after an election in Brazil, but before the date for the election runoffs. Turned out the voting machines couldn't be changed to handle the time change. Solution? They just pushed back the date when DST started until after the runoffs.

http://statoids.com/tbr.html -- "Note that the government frequently changes its mind [about DST] at the last minute."

Yeah, this list is woefully incomplete. Here's another good read: http://naggum.no/lugm-time.html
Oh man, I read that article years ago, lost the link and have been unable to find it since. Thanks! Any technical document which starts with "The measurement of time has a very long history, dating back to the first records of human civilization" and has a section titled "Political Time" gets a special place in my heart.
Also, computer systems have different Gregorian calendars. Your system could use the proper Gregorian calendar and a system you're communicating with could be using the proleptic Gregorian calendar. Most people don't notice the difference because dates aren't frequently slung around < 1582 in the modern world, but if a system has an idea of an "unset" date being equal to 1/1/1 it could lead to an error if transmitted to the other, resulting in an invalid date 12/30/0.
Not to mention dealing with the numerous differences in when the Gregorian calendar was adopted, which is great fun if you need to deal with dates even back to the early 1900's across borders.

E.g. the "October revolution" falls in November - Russia didn't change until the Bolcheviks took power in 1917. And Greece didn't switch until 1923... China switched in 1912, but different factions in the civil war used different systems and it wasn't until 1929 they got a single (Gregorian) calendar again.. And there are many other countries that switched "recently".

Let's keep some perspective. The vast majority of software applications don't use dates from the 18th century so it's fine to for your app to assume that the Gregorian calendar always was and always will be.
...except that there were countries that weren't using the Gregorian calendar until well into the 20th Century, so you can't even reliably deal with dates as recent as the mid-1900s across borders under that assumption.

But don't worry, they're just small countries.

Like Russia.

And China.

I suspect that even in China and Russia, most software will require that dates be entered as if the current Gregorian Calendar had always applied.
Software makes assumptions, though most decent time libraries will correctly combine local and date to show the skipped days. It might be a bit lazy though, running "cal sept 1752" will show the same for all locals as far as I can tell from the man page.
Imagine a historical database of Russian birthdays, copied from historical archives by data-entry clerks who had no idea when Russia switched from the Julian to the Gregorian calendar. (For extra fun, imagine that half of the clerks doing the data entry converted the dates before entering them, and half didn’t.)
39. The next day after 3 Sep 1752 is 4 Sep 1752.
I love that people in this thread think the adoption of the Gregorian calendar happened on a single date, it's way more complex than that.
In Sweden there was a 30th February 1712
In the British Empire/UK.
If only someone would come up with a standard time format, surely that would solve all issues...

In all seriousness time-stamps are some of the most annoying things to compare ever.

The comment about KVM in CentOS is probably inaccurate--not sure what it's referring to.

In the 5.4-ish time scale, there were a lot of clock related problems. One of them had to do with frequency scaling...

PCs have many time sources. The processor has it's own internal clock that ticks at a very fast rate (nanoseconds). There's the wallclock time which ticks at a slow rate (seconds). The internal clock starts at 0 when the system boots so it can't be used for wallclock time without adjustment.

Some Operating Systems (like Linux), get the boot time from the real time clock (slow tick rate) but then compute the current time by adding the CPU internal clock to it.

The CPU internal clock (TSC) can be wildly inaccurate for various reasons. One of them is frequency scaling which actually changes the frequency of the TSC dynamically. Unfortunately, if you're changing the frequency of the TSC on the host, guests that are running and accessing the TSC directly don't realize this has happened.

So if you scale the TSC frequency by 50%, time starts moving 50% more slowly. BIOS can also scale processor speed on some servers without the OS knowing which can lead to the same problem on bare metal.

More modern processors now have fixed TSC frequencies and KVM now has a paravirtual clock source both which address this problem.

BTW, Windows does not use the TSC as a time source so Windows typically won't have this problem (although it has other problems).

Time keeping in virtualization is fun :-)

35. People will just assume all APIs and standard libs that deal with dates are sane

Adobe managed to build a pretty shitty Date object for ActionScript that takes days as a 1-indexed parameter, but months as 0-indexed. Hopefully ActionScript is not used in banking [1]

[1] http://help.adobe.com/en_US/FlashPlatform/reference/actionsc...

This is not that insane, or at least relatively insane, because this matches the behavior of localtime(). I have heard the reason for using a 0-indexed month is for the convenience of mapping to an enum of month names.
IMHO a default month of January makes rather little sense, and would tend to facilitate subtle bugs... it seems you'd want the user to specify a month always, or maybe have a default of "indeterminate" or "Nevember"; the first position of an enum is very often the "nothing" case.
How about, "the difference between two timestamps is an accurate measure of the time that elapsed between them".
What's wrong about that? Numerical issues due to the truncation (ie 2500ms → 2s) and subsequent subtraction? Leap seconds? Anything else?
Measurement error, and the fact that the timestamps may not be taken on the same machine.
It isn't? Can you explain that in a bit more detail?
Some examples that come to mind:

1) You're (possibly) assuming that both timestamps come from the same machine. They could be from two machines (Server timestamps a transaction start, client timestamps the end.) Clocks are not accurate, so the delta time is not correct.

2) Time A is before a DST change forward or back, Time B is after. Delta would be wrong by +/- 1 hour (assuming all other factors are tracking with accuracy.

3) Both times are taken on the same machine, but far enough apart that clock drift plays a factor.

4) Both times are taken on the same machine, but an ntptimesync cron job kicked off in between them and adjusted the system clock.

#4 is why you really should be using ntpd(8): after syncronization, NTP will try to slew the clock if the difference is less than 128ms, step it if it's offset is between 128ms and 1000ms, and will exit with an error if the offset changes to be greater than 1000ms.
(comment deleted)
Timestamps are not affected by (or aware of) DST. In fact that's one reason why it's so easy to compute the time elapsed between two timestamps. From [0]:

  $ ./timetool 1130647000
    1130647000   =  Sunday  Oct 30, 2005  00:36 EDT
    1130647600   =  Sunday  Oct 30, 2005  00:46 EDT
    1130648200   =  Sunday  Oct 30, 2005  00:56 EDT
    1130648800   =  Sunday  Oct 30, 2005  01:06 EDT
    1130649400   =  Sunday  Oct 30, 2005  01:16 EDT
    1130650000   =  Sunday  Oct 30, 2005  01:26 EDT
    1130650600   =  Sunday  Oct 30, 2005  01:36 EDT
    1130651200   =  Sunday  Oct 30, 2005  01:46 EDT
    1130651800   =  Sunday  Oct 30, 2005  01:56 EDT
    1130652400   =  Sunday  Oct 30, 2005  01:06 EST
    1130653000   =  Sunday  Oct 30, 2005  01:16 EST
    1130653600   =  Sunday  Oct 30, 2005  01:26 EST
    1130654200   =  Sunday  Oct 30, 2005  01:36 EST
    1130654800   =  Sunday  Oct 30, 2005  01:46 EST
    1130655400   =  Sunday  Oct 30, 2005  01:56 EST
    1130656000   =  Sunday  Oct 30, 2005  02:06 EST
    1130656600   =  Sunday  Oct 30, 2005  02:16 EST
    1130657200   =  Sunday  Oct 30, 2005  02:26 EST
  $
So it's down to the accuracy (and synchronicity) of the clocks used to measure the timestamps: The difference between two timestamps is an accurate measure of the time elapsed (but see below), but that's probably only useful to you if the timestamps themselves are accurate.

However, leap seconds -- during which time passes, but the timestamps typically do not -- and numerical issues stemming from truncation and subtraction do have a systematic impact and reduce the accuracy of the difference. You can address the former for timestamps in the past by simply taking into account the leap seconds; you can address the latter by using higher resolution timestamps, ie. using millisecond timestamps if you need better-than-second-accuracy for the amount of time elapsed.

[0] http://www.unix.com/unix-dummies-questions-answers/18754-tim...

True, but that depends on what exactly you're reading as a timestamp.

Using localtime in perl for example (a very common method to read the system time) does not return a timestamp, but returns a formatted string (see: http://perldoc.perl.org/functions/localtime.html) that could easily be thrown off by a DST changeover.

What about time can you depend on?
You can't. Time is a completely relative concept. If you expect order, use a sequence.
I've been on an airplane (on the flight deck - pre 2001) watching the sun rise in the West. Sometimes local time runs backwards.
So, were you on the Concorde, or was it a Tu-144?
The terminator is only that fast near the equator. Further north, " ... it is possible to walk faster than the terminator at the poles, near to the equinoxes. The visual effect is that of seeing the Sun rise in the west."

http://en.wikipedia.org/wiki/Terminator_(solar)

Cool! So you could find a spot somewhere up north where you can take a stroll and experience an eternal sunrise/sunset. Very romantic :)
You didn't mention any assumptions that get screwed up by the presence of leap seconds.

N. There are 60 seconds in every minute. N+1. UNIX timestamps always advance monotonically.

N+?? The time library in your programming language is correct.

Every time library I've ever dealt with will have serious problems with at least one issue listed on the original article or in the comments here. JodaTime (on the JVM) is by far the best, but even they have problems, and are creating a new library to solve those.

> and are creating a new library to solve those.

Now they have N+1 problems.

I think that for the vast majority of real-world software applications JodaTime is bloated and unnecessary.

Most applications need only three 'classes' to represent time:

1. A timestamp (ie. number of milliseconds since midnight on 1 January 1970 GMT)

2. A Gregorian Date (ie. three numbers representing day, month, year)

3. A TimeZone (to convert between 1 and 2)

In Java the first and third types are perfectly represented by java.util.Date and java.util.TimeZone. The second class can be represented by something like this: http://calendardate.sourceforge.net/

(Disclaimer: I wrote CalendarDate)

1. A timestamp (ie. number of milliseconds since midnight on 1 January 1970 GMT)

You know that's not unix time, right? Unix time doesn't include leap seconds.

Hmm...I did not know that! I should really have said 'eg.' instead of 'ie.'

The point of the above 'timestamp' is is to represent a specific instant in time, independent of any time zone or calendar system. You can use Unix time for this purpose.

Depends. unixtime is for seconds, if you want to record 2 things that happen ¼ second apart, they might have the same value.

Also during leapseconds, unix time does funny things, like 2 second long 'seconds'. or it goes backwards to reset etc.

> N+?? The time library in your programming language is correct.

That is almost always a better assumption than “I can write a better one”.

> 32. A time stamp of sufficient precision can safely be considered unique.

I'm so guilty of that one.

This sort of stuff is why I scream "NNNNOOOOOOOOOOOOOO!!!!!!" when people store date/time as integers (i.e. "unix timestamps") when almost every database and programming language has a proper date or datetime data type, and a boatload of library functions that correctly compute differences between dates, handle leap years and time zones, etc. Well maybe not always correctly, but it's more likely that YOU will screw up your date math than it is that the well-tested date library will.
At least in Java, storing a date/time as a primitive improves immutability and is a good pattern.

You don't expose the underlying long value publicly so you end up with something like the following:

private long primitiveDate;

public Date getDate() { return new Date(primitiveDate); }

-----

This prevents calling methods from doing something stupid like:

o.getDate().setTime(123455L)

to modify a date that shouldn't be editable.

Or possibly better:

private Date date;

public Date getDate() { return new Date(date.getTime()); }

Your code solves the external side effects problem but using the primitive also allows the time to be finalized eg:

private final long creationTime = System.currentTimeMillis();

so it still has advantages over making the field a Date object.

> when almost every database and programming language has a proper date or datetime data type, and a boatload of library functions that correctly compute differences between dates, handle leap years and time zones, etc.

In Unix-land, this data type and boatload of library functions is the operating system. The system provides and deals with local time conversion when necessary. If your application isn't very involved with time (eg. it's not a calendar or scheduling application) then it is sensible to use Unix timestamps.

This ties you to a Unix OS, which isn't usually too bad a decision since other more important things do as well. On the other hand, using your programming language or database ties you to that database or language, which is arguably worse.

> In Unix-land, this data type and boatload of library functions is the operating system.

Which can lead to problems as well. Basically when dealing with "local" time (DST), you need a reliable source of data and the question boils down to whether you want system administrators to keep OSes patched and up-to-date every time tzdata is updated, or whether that should be handled at the application layer.

Java chooses to bake in tzdata, and so do a number of other app-layer platforms. JS in the browser relies on the OS instead of bundling binary tzdata. Windows and a few commercial *nix platforms do not bundle tzdata either and maintain their own definitions. The crowd-sourced tzdata has demonstrated itself better than even what Microsoft ships in Windows. I don't know anyone who would claim a dataset other than tzdata is "better".

There might come a point in time where browsers have sufficiently advanced automatic patching invisible to the end user that they would be better off bundling tzdata internally rather than relying on the OS because they can guarantee their data is better in a higher percentage of cases. It all comes down to whose update system is more seamless and more likely to occur given all the external factors that come into play. (e.g., a user might have local machine privileges to apply browser updates, but not OS updates)

IMHO you will change your tune with more time and experience; numerics are often more portable and unambiguous than string or serialized-object alternatives... e.g., if you pass around datetimes as "int64 count of 100-ns intervals since 1-1-1601 UTC" there is little opportunity for someone who doesn't know how to use it to get a quasi-usable yet incorrect datetime out of it.

Also note, there are plenty of database systems that either have no proper datetime datatype, or have primarily datetimes that include no TZ info.

There's a standard for that. ISO 8601. Use that. Don't make up your own.
The '100ns ticks' example is actually the Windows FILETIME, not my own invention. ISO 8601 is fine and dandy for stringified datetimes, although it's my position that strings open the door to more errors when consumed or produced by lazy/poor programmers.
He missed the myth that "Time always moves forward"
The myth is "Time always moves equally forward everywhere".