It doesn’t really strike me as clever. Of the options available to them, they chose the most difficult to debug.
The options I see available are:
Add a new monotonic time function.
Add a new monotonic time function and modify the type of time.Now or change its name to reflect it is not monotonic.
Do this.
1 does not break backwards compatibility, however 2 and 3 do. 3 changes the semantics of Add and Sub to no longer reflect the current meaning. 3 also introduces a new class of bugs. I, personally, think 1 is the best solution in their case. It is always right and it does not introduce a new class of bugs, but the 30% of code would need to update itself to use the monotonic function.
I think it’s disingenuous to claim that this change is backwards compatible when it does change the meaning of Sub and Add.
The problem isn’t that this breaks equality (you’re right, time equality is messy), it’s that this changes further arithmetic with t to work with wall-clock time which effected by clock changes instead of monotonic which isn’t. It’s not like a few least-significant bits are off, it’s that real bugs can be introduced/removed by adding 0.
The thing is, sometimes you want non-monotonic time diffs, which is why they added this quirk in the first place. They should’ve bit the bullet and added a separate monotonic type. Or kept time.Now() returning both and added an AsMonotonic() or AsWall() method. Basically anything other than adding an implicit trick to otherwise-clear code. The effect of AddDate(0,0,0) matters, otherwise this changeset wouldn’t exist, and it shouldn’t matter, for the same reason adding 0 anywhere else shouldn’t matter.
“Make things as simple as possible, but not simpler.” - Einstein
I think this is a really interesting (and clever) approach to the problem.
It doesn’t really strike me as clever. Of the options available to them, they chose the most difficult to debug.
The options I see available are:
time.Nowor change its name to reflect it is not monotonic.1 does not break backwards compatibility, however 2 and 3 do. 3 changes the semantics of
AddandSubto no longer reflect the current meaning. 3 also introduces a new class of bugs. I, personally, think 1 is the best solution in their case. It is always right and it does not introduce a new class of bugs, but the 30% of code would need to update itself to use the monotonic function.I think it’s disingenuous to claim that this change is backwards compatible when it does change the meaning of
SubandAdd.From the proposal: “
t.Sub(u)(using monotonic clock readings) andt.AddDate(0,0,0).Sub(u)(using wall clock readings) will differ slightly.”Adding 0 meaningfully changes the behavior of your program. I would usually call this a bug.
Relying on exact equality between time values is a bug, similar to relying on exact precision from floats.
Further, non-monotinic time diffs create subtle, tremendously difficult to detect bugs.
The problem isn’t that this breaks equality (you’re right, time equality is messy), it’s that this changes further arithmetic with
tto work with wall-clock time which effected by clock changes instead of monotonic which isn’t. It’s not like a few least-significant bits are off, it’s that real bugs can be introduced/removed by adding 0.The thing is, sometimes you want non-monotonic time diffs, which is why they added this quirk in the first place. They should’ve bit the bullet and added a separate monotonic type. Or kept
time.Now()returning both and added anAsMonotonic()orAsWall()method. Basically anything other than adding an implicit trick to otherwise-clear code. The effect ofAddDate(0,0,0)matters, otherwise this changeset wouldn’t exist, and it shouldn’t matter, for the same reason adding 0 anywhere else shouldn’t matter.“Make things as simple as possible, but not simpler.” - Einstein
You know what else causes difficult to detect bugs? Forcing all calls to a read operation to go through a shared global consistency write lock.