Hacker News new | past | comments | ask | show | jobs | submit login
Falsehoods Programmers Believe About Time (2012) (infiniteundo.com)
183 points by kushti on Oct 10, 2016 | hide | past | favorite | 154 comments



I got two I noticed over the years:

* Didn't think about time at all.

In most cases most don't think about time until it becomes a problem. It often ends up with a system which behaves in surprising ways, and is the equivalent to the developer believing any of those things in the article. But there is a difference in them believing those falsehoods, and simply not being a aware of them at all.

* Time moves forward

This is probably the biggest gotcha of all. Just imagine how many times int the past you did dt = now() - t0, then did something with dt like sleep(dt). Well time will move backwards sometimes and dt is negative. I bet this will make most people here worried and they'll think about code they wrote like that (sure did). I have seen systems freeze for example because they end up sleeping for a huge amount of time (negative number was cast to an unsigned huge number).

A small advice on how to improve errors related to time is to abstract it away from algorithms and code as much as possible. Instead of always calling gettimeofday() / time() / now() function to get the current time, in a piece of lower level code, try to pass it in as an argument. That will make code testable.

I have seen fun failing test cases. Something like encoding the current time the test was written and a dt to current time. The test was working for years then started failing eventually because of the hard coded time.


>Instead of always calling gettimeofday() / time() / now() function to get the current time, in a piece of lower level code, try to pass it in as an argument.

Any code that uses time based scheduling should use a virtual implementation of time/scheduler to allow testing - this way you can say "sleep 10 hours" and then "move virtual time by 10 hours" and actually verify that the timeout is hit without the tests actually taking 10 hours. It also lets you test out logical edge cases such as `<=`, `>=` vs `<`, `>` which is surprisingly tricky with timeouts.


This is quite right. It is actually just a special case of "singletons are evil". People sometimes don't notice that "the system" is the biggest singleton of them all.

Now all we need to do is get rid of the filesystem and all other databases...


Shameless plug: libfaultinj [1] is my library that intercepts libc calls and does bad behavior (that you specify) instead/in addition.

It doesn't support this use case. Yet [2].

[1] https://github.com/androm3da/libfaultinj

[2] https://github.com/androm3da/libfaultinj/issues/2


Oh awesome. That is good stuff. I will have to try it.


Great idea! But how does one make a virtual implementation of time/scheduler?


Every function which returns the current time, should be dependency injected with a 'currentTimeService'. This service, during tests, is injected with your mock implementation, and during production with a simple call to 'new DateTime()' or sth like that.


I 100% agree.

I've pitched this before (during a code review for something) and was laughed at by the team under some guise of YAGNI / developer gold plating. They honestly thought I was joking. Once I explained the issues mentioned in the article, they still thought it was a waste of time.

It takes just a few seconds to implement and makes the code so much easier to test / maintain.


Tell them we're currently replaying test scenario's involving thousands of truck routes per day (and around a thousand trucks). This allows us to easily recreate bugs and see the effects of fixes, new algorithms, etc. etc. Couldn't do it with some DI on the whole system and simulated time.


Our solution in c# with dependency injection looks like this.

Any class that needs to know the time has the following object injected in.

  public interface IDateTime
    {
        DateTime UtcNow { get; }
        DateTime Today { get; }
    }
StructureMap is configured to pass in the following concrete implementation.

  public class DefaultDateTime : IDateTime
    {
        public DateTime UtcNow
        {
            get { return DateTime.UtcNow; }
        }

        public DateTime Today
        {
            get { return DateTime.Today; }
        }
    }
Obviously you can expand this to include local time, we haven't in order to prevent accidental use of Now when you mean UtcNow.

All of our tests inherit from a base test that does various set up stuff (clear down the db in integration tests for example). One of the things it does is swap out DefaultDateTime with this...

  public class TestDateTime : IDateTime
    {
        private DateTime _testDateTime;

        public TestDateTime(DateTime testDateTime)
        {
            _testDateTime = testDateTime;
        }

        public void ChangeTimeTo(DateTime testDateTime)
        {
            _testDateTime = testDateTime;
        }

        public DateTime UtcNow
        {
            get { return _testDateTime.ToUniversalTime();         }

          public DateTime Today
        {
            get { return _testDateTime.Date; }
        }
    }
Where _testDateTime is set to be sometime in August (always a good idea if you're developing in the UK!). This has the added advantage of making test runs deterministic (at least in this respect) even if you're not doing a time related test.


Sorry, what's the connection between August and the UK? Based in the US, but I can't think of a specific month I'd want my tests to run in.


It's summer time - during the winter the UK runs on UTC, so if you've forgot to do a timezone conversion you don't spot it until the clocks change in spring. Having tests use the time in summer make this easier to spot.


Not sure for sure but August is probably the least rainy/nasty month in England


What edejong said basically, Rx library uses this concept really well - you can see for example in .NET implementation [1] how the scheduler interface looks like. They basically abstract system timer and scheduling tasks, then you can implement you own virtual time implementation where current time is just a property that you can manually set, and when you change it you go trough the list of scheduled tasks and see if you need to execute any before the new current time.

[1] https://msdn.microsoft.com/en-us/library/system.concurrency....


I'm guilty of not following this enough. Hopefully I've learned my lesson - never put a NOW() in a sql query.


> (negative number was cast to an unsigned huge number)

Slightly off-topic pet-peeve of mine: never used unsigned, unless you have an extremely good reason for it. Saving one bit is not one of them. You never know when you will need to do arithmetic on your unsigned values. Time going backwards is a good example of this.


I am the opposite way. In my experience usage of signed where the underlying type is conceptually unsigned introduces subtle bugs. Whereas the defined behavior of unsigned wrap usually causes very obvious stalls and overflows. I have seen so many array access of -1 which never SEGV until you upgrade your compiler or change platform. Also pointers are typically unsigned, I suspect same-type operations are faster for array access... though I never have checked.


This crops up in Rust's std::time::Duration which has no concept of negative duration


If you think of time like a mathematical vector, the length of that vector can never be negative.. it's always >= 0.. sure, though, in 1D, encoding the direction of that vector as +ve or -ve is pretty convenient.


> * Time moves forward

I agree. Smart library developers seem to agree, too. Example from Python docs:

https://docs.python.org/3/library/time.html#time.monotonic

The only (cough) problem is drilling this knowledge into developers' heads - and as you said, awareness that there even is a problem!


>> time will move backwards sometimes

Can you please explain this one and hopefully link to an in-depth resource? I imagine you're talking about leap seconds, and/or the possibility that the system time is changed (whether manually or due to an ntpd update that corrects backwards). Are there other sources of this phenomenon?


Not the original poster, but I assume they mean daylight saving. Depending on which kind of clock you're talking about, then for most of the world time goes back by an hour.


Leap seconds are a big enough problem that stock markets shut down for them.[1] Google starts advancing their clocks hours in advance of a leap second. Power companies take about four hours to catch up after one. (Every 1800 RPM generator has to make 30 extra turns.) Very few systems properly handle a 61-second minute. Unix timestamps are fundamentally incompatible with leap seconds.

[1] http://money.cnn.com/2015/06/29/technology/leap-second/


"Every 1800 RPM generator has to make 30 extra turns."

I'm having trouble wrapping my my head around this one. If the goal is maintaining a steady output, shouldn't they keep revolving at the same rate, without worrying about what day the "current" second (no pun intended) belongs to? After all, I'm assuming they don't "catch up" after leap days, they just run for an extra day at the same output level. Why would leap seconds be different?

Put another way, what do they need to spread those extra 30 turns over a 4 hour catch up period? Weren't they given an extra second in which to take care of them?


A lot of systems use the 60hz (or 50hz depending on location) signal from AC power as a way of keeping time. It's used enough that power companies will actually adjust the frequency minutely at night in order to make up for any mistakes made during the day. (Which in turn makes it so reliable that more systems use it to track time, and so on...)

I guess grandparent post is saying power companies go ahead and feed in extra cycles for the leap second. It's not something I'd heard of, but it wouldn't surprise me.


Hmmm? In the UK I'm sure the frequency changes with load on the grid and is actually a way of measuring grid load.


Indeed, and they have to remain within +-1%. They have a realtime graph:

http://www2.nationalgrid.com/uk/Industry-information/electri...

Before quartz clocks were around, synchronous mains clocks were common, and accurate.


The idea is that while the instantaneous frequency varies with load, the power grid is actively regulated such that frequency is constant on average over longer periods (typically such that from midnight to midnight there are 24 * 3600 * 50 or 60 cycles).


I remember reading that the frequency at any given time is usually somewhere between 49.9Hz and 50.1Hz (and similarly around 60Hz I'd imagine). So for a 50Hz clock, it's not very accurate at all.

However, I just found that the _average_ frequency over a length of time should be exactly 50Hz, so it is, in fact, good for keeping time.

More here:

https://wwwhome.ewi.utwente.nl/~ptdeboer/misc/mains.html


As an example of reliance on this, the C64 had a (rarely used) realtime clock in the 6256 CIA's (IO chips) that relied on the AC 50/60Hz signal to keep the time of day. It also used it to control the cassette motor. For those reasons and a couple others, it took both 9V AC and 5V DC in.

(The machine would actually mostly run fine off just a 5V DC input, or even off a 4.5V battery most of the time if you didnt need any of the things that required AC...)


I remember hearing that Analog TV stations were also used for timekeeping since they had a very stable clock for the blanking interval


US analog TV (all three classic networks) used to be synchronized to an atomic clock in NYC. This allowed switching from one source to another without frame tearing.

Separate from that, there was a scheme for sending time of day in the vertical retrace interval, to set clocks and VCRs. Few devices received that, although I once encountered a hotel TV with a built-in analog clock that did. (The clock was wrong; although it could set itself automatically, it had to be told manually which channel provided a time signal. That's probably why this feature never caught on. I was bored enough to figure out how to set the thing.)

US telephony used to be synchronized to an atomic clock in New Jersey. The TDMA multiplexing was kept in sync so that frames could be transferred synchronously without buffering. If the clock connection was lost, T1 to T3 lines would get slightly out of sync, and occasionally drop or add an 8-bit frame. This is unnoticeable in audio, but an error for modems.

But neither of these was a time count. It was just a square wave.


Interesting to hear about how it worked in the US.

I think I heard about the TV frame syncing from an Australian YouTube video.

I'm from Europe where every TV and VCR would easily get a clock from TeleText (we also had fancy stuff like PDC to make sure your video recordings of TV shows didn't get cut off)


Your power company: The first NTP server.


Yes. "Electrically checked by your electric utility company to correspond with official Naval Observatory time." - General Electric clock ad, 1948.[1]

[1] https://books.google.com/books?id=W0oEAAAAMBAJ&lpg=PA9&ots=4...


The power grid doesn't work if disparate phases aren't synchronized. On a very large scale this is why HVDC is used, but on smaller scales its still more cost-effective to coordinate with GPS time since it's atomic-clock backed.


This (unfortunately, commonly-held) misbelief is solidly in Not Even Wrong territory. Parallel AC sources with inductive impedance are naturally synchronized to each other. A phase error between them produces a torque error that is naturally self-correcting.


In a power grid, the AC generators are basically synchronized and in phase. But there's some tweaking on phase to control which way power is shipped. Inductors and capacitors are switched in and out to induce small phase shifts and drive power in the desired direction. If you want to know more about this, there's online training called "PJM 101", from the power grid operator for the northeastern US.

HVDC systems are connected to AC systems using rectifiers and inverters. An interconnect point is a switching power supply. A very large switching power supply. The output DC isn't perfectly clean DC and the output AC isn't a clean sinusoid; converters have to approximate and try to filter. Wikipedia has a nice explanation, with good pictures.[1]

[1] https://en.wikipedia.org/wiki/HVDC_converter


This is the first I've heard of HVDC, and it's apparently a thing. However from my quick read, it's 1) still a frequency-based current, so you're not eliminating the requirement to synchronise generation, and 2) the advantages are in areas other than frequency synchronisation -- e.g., avoiding capacitance load in long-distance undersea cables.


What? WHAT? DC does not have a "frequency".


Damn, I guess it's been too long since I've done (or thought about) circuit theory. But yeah, the general idea of HVDC is a frequency-free current:

http://www.cleanlineenergy.com/technology/hvdc/how

And now I'm trying to think my way through it:

There is definitely DC with no frequency component, e.g., battery circuits. You've got a cathode, an anode, and a flow between them.

I'm trying to sort out if DC can have a frequency component. I seem to recall that rectified circuits can operate by basically (pardon crude metaphors) chopping off the negative side of the phase. You'll have a wave pattern, but it's all going in one direction. Pushed through sufficient capacitance or impedance and you'll likely smooth that out as well.

Which is getting me to wonder just how a DC generator works.


DC is synonymous with 0 frequency.

Your metaphor for rectified circuits is not crude, a half-wave rectifier will clip the negative portion of the signal to 0, a full-wave rectifier will actually invert the negative portion.

I wouldn't say you push it through sufficient capacitance or impedance, but you do want to smooth out this bumpy (now positive) wavy signal, so you low pass filter it, a simple resistor-capacitor circuit.

what we're describing is an AC/DC convertor


We're kind of off topic here, but ...

Ideal DC has zero ripple, and looks like a straight line on a scope. Ideal AC is a sinusoid. AC-DC conversion tends to produce some ripple. At low power levels, a capacitor across the line and/or an inductor in series will level out the ripple. At high power and voltage, such filters become huge, and there are lots of tricks used to reduce the need for filtering.

Converting 3 phase power to DC works better than single phase, since at least two phases are always delivering power. There's no zero-power point, as there is with single phase, and the ripple is at 6x the AC frequency. (The higher the frequency, the less filtering required.) There's also a trick with transformers for converting 3-phase power to 6-phase power. This gets the ripple frequency up to 720Hz. This is an old trick; the NYC subway system has used it for many decades.

Converting DC to clean AC used to be tough. The home solar power industry took a long time to get inverters with good output waveforms. Early inverters produced square waves, which overheat motors and transformers. There's been a lot of progress, and power semiconductors have improved enormously in recent years. Now everything from electric cars to Diesel-electric locomotives to electric model airplanes have 3-phase inverters. Anything with a "brushless DC" (really synchronous AC) motor has an inverter driving it. The output waveform is usually a stairstep approximation to a sine wave. This can be filtered into a sine wave if necessary.

Power MOSFETs make this all possible. It's incredible how good they are as electrical switches. Turn-on resistances are in the milli-ohm range. That's as good as a mechanical switch, and better than a carbon-brush commutator.


I think this is one of those allowed off-topic digressions :)

Thanks for the info.


Thanks for your patience.

There's a distinction between a current which reverses flow, and one which varies, perhaps regularly, but without reversing flow.

The reason coordination of AC generation is crucial is that if you pump opposing cycles at each other, they simply cancel out. If you pump out-of-phase varying DC currents at each other, they amplify one another -- the sign is always positive, but the magnitude varies. I suspect that might also cause problems, but not in the same way as a going-nowhere-fast out-of-phase AC circuit would.

The phase-damping (and I very vaguely recall damped driven oscillators from physics: friends don't let friends drive damped ...), wouldn't be an AC/DC converter, but a form of power smoothing / power conditioning, I believe.


> There's a distinction between a current which reverses flow, and one which varies, perhaps regularly, but without reversing flow.

[5, 3, 5, 3, ...] = [4, 4, 4, 4, ...] + [1, -1, 1, -1, ...]

Every current that varies with a regular frequency is just the sum of a DC current and an AC current that reverses flow. I guess in most applications one can decompose them and analyze the two components separately.


Sure, you can decompose them. But if you're outputting DC, again, you never have to worry about subtracting from an existing DC line voltage. If you're outputting AC, you have to worry about wave interference.


I was just talking about your distinction between a current that reverses flow, and one that varies without reversing flow.


There is no DC generator as such, just a converter from AC to DC.


Um, isn't a dynamo a DC generator?

https://en.wikipedia.org/wiki/Dynamo

It's described (and matches my memory) of producing a "pulsing direct current". The commutator, a physical switch, maintains the polarity of current by breaking and switching between generator coils.


iirc (been awhile since EE so could be wrong):

Dynamo is basically an AC gen with some crap in front to make output look DC.

"Pulsing DC current" is actually ac with >50% of the duty cycle zeroed out.

Again, could be very wrong here my memory is fuzzy as hell.


If I'm remembering and understanding correctly: the commutator swaps the + and - ends of the energised coil. So you're not actually zeroing out the inverted end of the wave, you're swapping its connections to the circuit. Where an AC generator coil applies a positive and negative voltage to a single lead, the DC generator swaps leads as the current reverses.

I'm glad I'm not the only fuzzy one here....


wikipedia seems to agree with you, if i read this right.

> A dynamo is an electrical generator that produces direct current with the use of a commutator.

>> A commutator is a moving part of a rotary electrical switch [...] that periodically reverses the current direction between the rotor and the external circuit


Take a DC motor, attach a load resistor, and spin it at constant speed. Look at the output voltage on a voltmeter. You will get DC output.


From Wikipedia (top of 2nd paragraph) "HVDC allows power transmission between unsynchronized AC transmission systems"


Do you have a source for grid frequency taking into account leap seconds? I had a quick look around for information about the UK grid and can't find any timekeeping details.

Also, wouldn't they have to slow down slightly rather than speed up? The second at midnight effectively takes twice as long, which is equivalent to the grid's waveform stopping for 1 second.


Dave Mills, the NTP guy, wrote about this. He'd watch clocks from various sources after a leap second to see what happened.


Sure is a problem when you are writing a system for processing stocks, not really if you are making a calendar app or ecommerce website.

I guess what I mean is that things like that are a nice piece of trivia, little fun facts, but nothing to be concerned of for most of us.


Until you assume midnight one day plus 24 * 3600 seconds will equal midnight the next day. These kinds of problems will bite you in all sort of places you don't think you need to worry about them.


Falsehood non-physicists believe about time: simultaneity.

https://www.youtube.com/watch?v=wteiuxyqtoM


This is a very interesting video by Computerphile on this subject: https://www.youtube.com/watch?v=-5wpm-gesOY


My experience is that for most applications, programmers really only need to understand 3 types:

1. An instant in time - often represented as an integer number of milliseconds since January 1, 1970.

2. A date in the Gregorian calendar. This could also be an integer offset from a particular day, but it's better to encapsulate it in a class that allows you to add days or months, get the number of days between two dates, etc.

3. A timezone which is necessary to convert between the two types mentioned above.

Java has default classes to represent Types 1 and 3, but is missing a simple class for Type 2. So I designed one myself: http://calendardate.sourceforge.net


I think the following ingredients are minimally necessary for normal day-to-day stuff:

1. For events in the past, a timestamp

2. For events in the future, a date/time pair with precision at least milliseconds and a timezone.

3. An ISO 8601 serialization/deserialization method

4. A duration type, which denotes a number of 'hours/minutes/seconds/days/weeks'.

5. A partial representation of date, to denote repeating events or events which last a whole day. The partial representation should optionally include a timezone. This allows me to say: '5th of May', or '22nd of November 1980, in CEST'.

For calculations of dates and times, it is very useful to have a notion of time intervals, durations of time and weekdays.


> For events in the future, a date/time pair with precision at least milliseconds and a timezone.

Hmmm...Can you give an example where that would be used? I'm thinking of a user who wants to be woken up at 7am even if they change their timezone. But that wouldn't require millisecond precision.

> A duration type, which denotes a number of 'hours/minutes/seconds/days/weeks'.. For calculations of dates and times, it is very useful to have a notion of time intervals, durations of time and weekdays.

Couldn't you do that with the first two types I mentioned? With two instances of Type 1 it's trivial to count the number of milliseconds between them. With two instances of Type 2 you can have d1.daysUntil(d2) or dq.monthsUntil(d2) etc.

> This allows me to say: '5th of May'...

Is that common enough and complicated enough to warrant an extra type? When I write code to process credit card payments, I just record the card expiry as two integers: expMonth and expYear. When I want to check if the card is expired I just create a Type 2 instance representing the last day of the month. Seems to me I could do something similar for 'repeat on 5 May'.


For the first example, a skype meeting with participants on both sides of the equator, or even just in countries where one has ended daylight savings time and the other hasn't yet.

That may seem like a special case, but it is relatively common, it might also matter for normal business meetings in a foreign country - UK time is an hour behind France, so if you are a UK business man trying to have a meeting in Paris, you need to take time zones into account.

It is never trivial to calculate the duration between two times, because you may have to take into account leap years, leap seconds, months that does not have the same number of days, etc, not to mention if they are in two different timezones. That doesn't mean it isn't possible, but it is not trivial.

What is the last day of the month? That depends on the month, and if that is February it also depends on the current year. If you need to process credit cards, you might need to know the last banking day of the month, which could be quite early during e.g easter. BTW to know when easter falls, your dating system needs to know about the lunar calendar.

This doesn't even begin to touch what happens in countries that celebrate Ramadahn.


Those are some interesting situations, but I think they can still be handled using the 3 types I mentioned.

A Skype call is actually a good example of when not to use a data type which encapsulates 'time zone plus instance in time'. That's because there is not one but multiple time zones associated with a single instance in time - each Skype caller will have his or her own time zone. The time of the call should be treated as a pure 'instance in time' without reference to any particular time zone. When it comes to displaying the time to a particular user, you would have formatting code which takes (a) the user's time zone; (b) the user's language; (c) a format pattern; and (d) the instance in time; and returns (e) a string representation of the time for that user.

If the computer's clock is based UTC it is trivial to find the duration between two 'instants in time': it's just t2 - t1. An instant in time (what I called Type 1) is independent of any calendar system so months, leap years, time zones, etc. don't matter when calculating the duration between two Type 1 values.

However, in practice most system clocks are not based on UTC but rather Unix Time [1]. Due to leap seconds, such clocks do not always 'tick' in a monotonic way. So I accept that it is usually not trivial to accurately find the duration between two times. But the solution is not to burden the programmer with an extra type - instead, just add a method to the existing 'instant in time' class like this: t1.millisecsUntil(t2).

To find the days in any given month, a 'date in the Gregorian calendar' class (what I call Type 2) can handle that easily - just call the daysInMonth() method. Again, no need to create new type.

Easter, Islamic dates, Buddhist dates, banking days, etc. are all based on Type 2 - ie. an abstract concept of a 'day' without reference to any time zone or any particular instant in time.

[1] https://en.wikipedia.org/wiki/Unix_time


The Skype call is always in reference to a certain perspective of 'time-of-day'. So, you'd say: I will call you at 13.00 CET, which is 14:00 GMT at my place. When we move it to the next day, it will be in reference to CET and DTS will be taken into account in CET, not in GMT. As long as humans see time as a location dependent aspect, it makes sense to inform them of the reference that has been used (being the timezone). Another way to say this is that the Skype call, or the appointment, will be scheduled at a time and timezone of someone's perspective. The other participants need to see the appointment in reference of that.

The duration in milliseconds is (almost always) easy to find. However, you often want to find the duration in months, weeks, days, etc. etc. This again requires a reference timezone and calendar system.

Your 'type 2' day is actually very difficult to define. For example, when I talk about the 12th of October 2016, I will see it as a time-interval in central European time. Your time-interval might be different. By the way, you can only handle the daysInMonth case. Other examples would fail: weeksInMonth, weeksInYear, hoursOfMonth, etc. etc.


When scheduling an appointment (event) in the future and you need to move it around, these fields are necessary. Repeating events are similar, as you already mentioned. Millisecond precision is just the standard. I would say nanosecond should be the standard, but it isn't yet.

The durations are very useful for basic arithmetic on time. An hour isn't always an 60 times 60 seconds (leap seconds) and a day isn't always 24 hours. So, if you have two buttons in your UI which move your appointment around, or which calculate the end-time of a one-hour appointment, you want to be able to use the type '1 hour', and not 60 times 60 times 1000 milliseconds.

The partial dates are very common and miscalculations are often made. It is notoriously difficult to calculate with partial dates and warrants a type with associated methods/functions. I see myself often writing something like: `new LocalDate(5,5).toInterval().contains(now)` (where obviously, the localdate is automatically deserialized from JSON or sth alike).


Good list, sadly many (most?) popular languages have difficulties fulfilling it, sometimes even if you include third-party libraries...


> 1. An instant in time - often represented as an integer number of milliseconds since January 1, 1970.

POSIX time is actually not the number of seconds since 00:00 UTC on January 1, 1970, but the 864000 times the number of days since January 1, 1970, plus the number of seconds since the start of the current day.

See "1. There are always 24 hours in a day" (or rather, there are always 60 seconds in a minute, since the leap second makes the last minute/hour of the day longer, so there are still 24 hours in the day)


OK yes, it's more common to use POSIX 'ticks' to represent an instant in time. The point is: Type 1 is an instant in time, is independent of any timezone or calendar system, and is usually represented by an integer.


> OK yes, it's more common to use POSIX 'ticks' to represent an instant in time. The point is: Type 1 is an instant in time

I'm not sure what a "tick" is, but POSIX time often purports to be the number of seconds (or similar) since 1970, (and thus, represent an instant in time) but in practice it isn't; that's the point of the parent poster: it's precisely the definition that he or she gave. (It's the number of days times a constant, etc.) While usually POSIX time represents an instant in time, it becomes ambiguous during leap seconds, and duration calculations with POSIX times will almost invariably be just arithmetic on the underlying value, which is going to be wrong over certain intervals (any interval crossing a leap second).

For the most part, nobody notices, but this is where and why weird bugs crop up.


> 1. An instant in time - often represented as an integer number of milliseconds since January 1, 1970.

That's already an undefined statement ;-)

I mean, I guess you are actually aware of it, but that's not actually an instant in time, that's about 24 different spans of time, each 86400000 milliseconds long.


It took me a while to figure out what you are pointing out.

GP left out the time and timezone, but we still recognize that date as shorthand referring to the Unix epoch.


Whoops sorry I should have said January 1,1970 GMT!


Did you see Java 8's java.time classes? There's LocalDateTime for type 2, and Instant which is like a much improved Date. Both obviously Joda inspired.


Thanks - I didn't know Java 8 had incorporated Joda time.

Actually LocalDate is a better representation for Type 2 because it doesn't encapsulate minutes, hours or seconds. This would make it ideal to represent "John's birthday" or "date on which the customer repaid loan".

In fact, I'm disappointed that Java has incorporated Joda time - new Java programmers will now need to crawl over a huge pile of time-based classes to pick out the ones they need, when for 99% of cases only the same 3 types are necessary. How many of these novice users will incorrectly use LocalDateTime to represent Type 1?


To be fair, they didn't literally incorporate Joda, the new library is "heavily inspired" by it. It has way fewer classes, organized into a very sensibly named hierarchy.


The Joda-time author (jointly) led the JSR for this.

http://www.oracle.com/technetwork/articles/java/jf14-date-ti...


Yes, but the java.time package is significantly smaller, and much improved in my opinion. For example, Joda has a few mutable structures, while java.time is 100% immutable.

I still don't like how you can do things like Instant.from(DayOfWeek.MONDAY) (which results in a runtime exception), but at least at least it's slightly more type-safe than Joda, wherein all the conversion methods take an Object parameter.


My favorite time-related false beliefs are about time zones:

1. 1AM happens 24 times a day

2. Ok, so 1A is screwed up because of DST. Noon happens 24 times a day.

3. The maximum distance between time zones is 24 hrs

4. Time zones are in 1hr increments

5. In half hour increments?

6. UTC offset is a good thing to store in someone's profile

7. People live in a fixed number of UTC offsets


I ran into this a while back when I wanted to make sure every user got emailed a report at 6am, Monday morning, their local time.

My chosen solution was a script to be triggered by a cronjob that ran when reports needed to be emailed out, but not otherwise, eg, at 6am in every timezone, every Monday. All I needed to do was figure out what times those were. Simple right?

It didn't take long until I realised I needed to make some concessions to reality. :)


I think my favorite if I remember correctly Arizona doesn't follow DST. The Navajo Nation does, but the Hopi do not. The Hopi Reservation is inside the Navajo Nation. But there is and area of Navajo Nation inside the Hopi reservation. There are also a large number of discontinuous bits of Navajo Nation.


I am from Arizona; you are correct.

No DST is awesome, but causes no end of coordination problems with people outside of AZ... for important meetings like job interviews basically the only option is to be prepped on both hours.

The reservation thing is fun with cell phones - in northern parts of the state, there are places where your cell phone will adjust time by an hour depending on which cell tower you manage to connect to. So one moment your screen will display 2:30, the next 3:30, and a few minutes later it's back to 2:30 again. You fall back to using relative times; "we'll meet in an hour, etc."


I still wear a watch because of reasons like that.

(I look at my watch, I have 2:30) "What time do you have?"

"3:30"

"Ok. Let's meet in an hour. That's 4:30 for you." (Which I know will be 3:30 for me)

My watch also runs for years on a single battery. I probably get asked for time once a week by somebody whose phone has died. (Wearing a watch is the universal symbol for "I have the time")


Add to it:

Time zones change linearly from east to west and west to east

For each physical location there is exactly one time zone


> For each physical location there is exactly one time zone

Care to elaborate?


Not sure if it's what they meant, but the boundaries move, so the timezone you store in a location today may not be the one that it corresponds with in a year.

https://en.wikipedia.org/wiki/Time_in_Indiana


I don't know of any parcels of land that are simultaneously in more than one zone, but I do know that (until recently?) Indiana used to change time zones from Eastern to Central instead of using DST.


I knew that.

What I understood was same geographical location with several time-zones at an instant in time.

Modulo border disputes I don't know of any such thing.


There are several places on earth that have an official and unofficial time zone, chiefly on time zone borders - some places in Indiana, for example, and the far western part of China where the time zone varies from solar time very significantly.

In those places, if you ask a user where they are, and then show them a time zone based on that, it may not reflect what they think.


You can also add:

* One geographical location won't change its timezone over time

* Apart from DST, one geographical location won't change its timezone over time

* If a location changes timezone, the leap is always less than an hour, maybe a few hours

* Ok, less than a day

* Why are you talking about 2011, December 30th in Samoa Islands?


And:

The time zone you use is a matter of geography, not political affiliation.


Understanding that point suddenly makes half of the list much more obvious.


5. Hah. One of my favorites... 45minute time offsets. There is a good list here: https://www.timeanddate.com/time/time-zones-interesting.html


A friend of mine and I partially decloacked anscammer using this recently; the caller allegedly being somewhere in the US, when asked what time it was responded with a time that was a half hour increment off from any current us time. Ergo, they were living in an area with 30 minute time zones.


That the clock always moves forward.

As one example, some clocks are cpu specific (rather than system specific). When a thread gets scheduled to a different cpu, it might be talking to a different clock, and getting a backwards time.

The user might also be changing the clock while the program is running, of course.

If the forward direction of time is important, make sure the the source of time is a monotonic clock API.


All I can add is a warning about running NTP if you are maintaining a priority queue of time-stamped actions (now + delta, where delta depends on the action): use CLOCK_MONOTONIC instead of wall time.


One recently that bugs me to no end, is someone at the company I work for created an API that takes a date parameter in YYYY/DD/MM format... wtf?!? YYYY-MM-DD is fine, when year is first, the month should always be next... that's universal at this point. mm/dd vs dd/mm is a problem, but it's always ymd when year is first. sigh

The issues with timezones, and offset calculations can be problematic too... fortunately most environments and language platforms have systems in place to at least convert to/from local to utc, while that doesn't resolve for time drift, or mis-set times, it does handle a lot of issues to always use utc, or use date/time + location if not using utc...

Another hard one is leap minutes/seconds, daylight savings time changes, etc.


In US a lot of paper forms use yy-mm-dd. America has crazy units and standards.


US is MM/DD/YYYY for most paper forms... whenever year is first, it's always year-month-day, period.


Time education in practice:

The linux kernel boots 5 minutes before the end of time, so that anyone whose code would break when jiffies wraparound will see that breakage soon after boot. That's a great, great feature.


Out of curiosity, what does the kernel consider 'the end of time'? Int 64 maximum?


uint32.


Care to elaborate on that?


The linux kernel's basic time unit is the jiffy, which wraps around every ~497 days and is visible to userspace using clock_gettime(CLOCK_MONOTONIC). In order to make sure that bugs don't occur only after 497 days, the jiffy value doesn't start at 0. Rather, the boot-time value is such that the jiffy value will wrap around after five minutes.

One of my brothers worked for an embedded device manufacturer that got bitten. The software worked great unless it was started in the first five minutes after a reboot. But since booting and waiting five minutes is easy, the fix was, too.

The nonzero boot-time value made it simple to fix a bug that occurs every 497 days. Fantastic, say I.


What a great solution! It's a "hostile" move that probably ends up preventing countless bugs in high-uptime systems.


Ha, looks like they did not fix the bug?

That is, they did not account for wraparound, they just avoided it. Is that correct?


Where my brother worked, you mean? They ensured that their software measured speed correctly in the hosts's fifth minute of uptime, and in all other minutes too.


I had some fun ones a couple of years ago on this theme:

* Every week has a weekend

* Weekends are always Saturday and Sunday

* Weekend days never change within a locale

* Weekend days are always on consecutive days


Are you talking about historical dates and calendars, or maybe different cultural calendars? Could you provide some examples? In the US today I don't think these four falsehoods are ever false.


I imagine the concept of weekends, as related to most computing, has to do with a work schedule.

Back when I used to work the night shift on non-standard days, doing any kind of scheduling with an electronic device was a real pain. Even today many scheduling tools don't cope well with overnight meetings.


Notably, Muslim countries often have a the Friday off, so sometimes the week-end is Friday/Saturday, in other countries it is Thursday/Friday.

https://en.wikipedia.org/wiki/Workweek_and_weekend#Muslim_co...

Another example from the same Wikipedia page :

> Brunei Darussalam has a non-contiguous working week, consisting of Monday to Thursday plus Saturday. The days of rest are Friday and Sunday.


And then there's:

* Weeks always start on Sunday

vs.

* Weeks always start on Monday


Yep, that's the context we had. An EMEA app that had a 20 day calendar, had to handle different weekend dates, different start of week days and different text directionality.


I discovered this one, recently:

> Excel stores dates as sequential serial numbers so that they can be used in calculations. By default, January 1, 1900 is serial number 1, and January 1, 2008 is serial number 39448 because it is 39,447 days after January 1, 1900.

That's from the Microsoft's documentation of Excel[1]. Note this part: "because [Jan 1, 2008] is 39,447 days after January 1, 1900"

  In [3]: (datetime.datetime(2008, 1, 1) - datetime.datetime(1900, 1, 1)).days
  Out[3]: 39446
Off by one, Microsoft. And yes, Excel does the same thing — i.e., the docs match the product.

If you're wondering why, it's b/c Excel incorrectly thinks that 1900 is a leap year. (Also, this is why a lot of Window's clocks track time since 1901, as it makes leap year calculations simpler… for now.)

[1]: https://support.office.com/en-us/article/DATEVALUE-function-...


I recall reading somewhere on Joel on Software that I can't find at the moment that Microsoft did this deliberately to duplicate a bug in Lotus 1-2-3, because they needed perfect compatibility with formulas and dates with 1-2-3 to get people to switch over. And Lotus 1-2-3 reportedly had this bug because, at the time it was written, the code to account for that case correctly legitimately took up too much space and was dropped, with Lotus figuring that not too many people would notice. And of course, Microsoft can't change it now, or else they'll potentially break a ton of people's spreadsheets that already work around it.


Let me just throw Easter in there, since nobody else has..

https://en.wikipedia.org/wiki/Computus

http://aa.usno.navy.mil/faq/docs/easter.php


One thing I've had to explain to many programmers, at several different jobs:

* A timestamp is not a date.

Many people believe a timestamp is a "more detailed date". In reality, every timestamp is in (at least) two different dates, depending on what timezone you look at it in.

The terrible java.util.Date is probably one reason.


I have two suggestions, one useful and one less useful:

1) Given two events that happened in two different locations, one happened before the other or they happened at the same time [1]

2) All the devices comprising your system will agree on what offset each timezone is (alternatively: will have the same version of the tzdb)

Number 2 is not a theoretical problem: if you have users in a country where the timezone can change at short notice (e.g. Turkey), how do you handle the fact that across all the different Android versions their phones will have different opinions on what the time is and what timezone they are in?

[1] https://en.wikipedia.org/wiki/Relativity_of_simultaneity


(1) is not a theoretical problem in distributed systems. I work on a system that involves malicious actors such that allowing subtle timing problems can cause very real revenue impact, and defining consistency in a way that converges quickly with only what amounts to a vector-clock definition of time is tons of fun.


I was deliberately careful with the wording - yes, in distributed systems, we may be unable to determine which event came first. But one of them did happen first in reality, we just can't tell which. However, in some cases (see the Wikipedia link) it's not even true that one of them did happen first - it depends on where you observe them from and there is no definitive answer! Relativity is weird.


A case like this, which has a wide variety of exceptions that need to be updated as timezones change (yes, they do) is a perfect case for a library. The best I've ever found was JodaTime, but I no longer work in Java and no other language has an equivalent.


Joda Time was "adopted" as a part of java 8 on the java.time.* packages.


Yeah, but that happened to late to help me. :/


Dates and times, floating point numbers, even strings... there will be always magic in how data is represented/encoded.

Now in the case of dates, there's the epoch, and a precision determined in terms of that epoch, there are compatibility workarounds between 32-bit and 64-bit time... we add have leap days and leap seconds, and of course: the fact that clocks go out of sync, timezones and daylight saving time, as well as a long long list of things.

Some countries move dates for DST every year.

Then, there are days that "do not exist" (September 1752 in UK/US, etc, when they moved from the julian to the gregorian calendar).


Previous discussion: https://news.ycombinator.com/item?id=4128208 (4 years ago, 213 comments)


For iOS devs: mach time is just a more precise, monotonic equivalent to wallclock, and it never pauses :p

See https://developer.apple.com/library/content/technotes/tn2169...


It looks like some of these should be taken care on the operations side. Sort of like https://12factor.net/

As a programmer you need to be able to make assumptions, otherwise it gets crazy complicated.


This list seems to imply relatively is only important orbiting black holes but the GPS satellites are far enough from earth or orbiting fast enough (both apply to satellites depending on orbit height) that relatively applies and the clocks have to be adjusted.


if you think dealing with time is a problem, try measuring elapsed time on computers that sleep :)

the solution i found (when dealing with this problem in C# a few years ago) is that you need to poll the time in an update loop (running at, say 10hz or whatever resolution you need). if you have a sudden jump in time between two loops, chances are the computer was asleep.

or there was a leap second.

or you are sampling local time instead of UTC and daylight savings just occurred, or the user crossed timezones.

or the user changed their clock manually.

Or the computer resynced with the time server (happens quite often, and can cause negative time to elapse. Better check the CPU for elapsed ticks instead!)

man... this is starting to sound like roll-your-own-cryptography ;)


More interesting falsehoods in this awesome list: https://github.com/kdeldycke/awesome-falsehood


Nice. Includes the one I'd just posted as well.

I recommend submitting that to HN. Looks as if it was a couple of months ago, but definitely worth the resubmission as it didn't take:

https://hn.algolia.com/?query=https:%2F%2Fgithub.com%2Fkdeld...


Much needed. Thanks. Handling time is difficult, and Java's api(older ones) didn't make life easy. I have fixed many subtle bugs in my code related to time, over the years.


I have had my fair share of dealing with these over the last decade.

pulling data from processes that run in different timezones and trying to merge that all together has been really fun.


I appreciate the list of things to look out for, but what about solutions? That would increase the value of the article immensely.


Also: * Leap years occur every 4 years


* Timezones never change


I've got 2:

-Your clock works the way you think it does

I was working for a company that makes pico-second clocks. It turns out, that all clocks experience drift. Like a gyroscope, each clock has it's own peculiarities and hyper-local environment, and like a gyroscope, they all tend to record and count time in different ways. If you have a clock, you know what time it is. But if you have 2 clocks, you are never sure. Now, we extend this to many clocks and we then have an ensemble of them, and (thank god) it ends up being a normal distribution that we then take the mean of. Now with picosecond clocks, the local gravitational environment, temperature, wear history, etc all end up being very big factors in time keeping. For most systems, this would be a catastrophe. You'd have to bury the clocks in some mountain, gravitationally 'shielded' away from things, temperature controlled, super clean, etc, and only take the time once a day or something. It turns out that if you run those calculations, you can only keep time to a part in 10^-16. Fortunately though, we discipline time to that of the Earth. Days and years are the thing we must subside to. And these things are only good to about a part in 10^-12, so we have 10,000 parts of 'error' to live in. It turns out, the Earth is a pretty bad clock, overall. It was pretty cool, years after I left that job, to walk into NIST and see an ensemble of our old clocks in the room where the US second is measured.

-Leap seconds always occur on the same date/time of the year.

The terrible earth-quake in Fukushima really did a number on the international timing community too. The change in distribution of mass of the Earth was so much that it slowed the year down by ~1 millisecond in total. I hope that the readers of the article and the rest of the comments here can appreciate that such a change, though to a normal person is small, is actually quite a lot for computers and other logic based systems. The 'leap-second', in reality a millisecond, was chosen to occur not on the last night of February of the following year, but was pushed forward to the last night of June. This did not make the people that sell super precise clocks very happy. Typically, the leap-second night is one of mayhem for clock sellers and the people that support the sold clocks. As this usually happens at midnight, far past when you have to put your kids to bed, the 'push notification' of the new time is in weary hours. That means starting about 1 minute after midnight, you start getting flooded with calls from your customers. Now, the purchasers of hyper-precise clocks tend to be very wealthy and powerful and very angry and sleepy that all of their very expensive computers are now 'all broke'd' in the literal middle of the night. Most of the time, you can reach out to the IT guys of these large oil&gas, Wall-Street, military, educational, and other types of firms and make contacts and let them know things will start to get out of whack. And they tend to learn that this usually happens in early March. Well, for this end of June leap-second, we knew things were going to be hairy. And they were. I was not even close to senior enough to be on those calls, but I came in the next day and all the senior guys were STILL on the phones with the various companies. When I left, they were on the phones still. I think they must have been up for at least 50 hours, judging by the amounts of RipIts scattered about the floors. That is what I call a salary job.

In all, I learned that humans think that time works in one way, but it really is 'what a clock measures' and is an abstract concept we put a lot of value into. And no, we will never be able to make a program that can take all of these considerations into account. All that will do is make the troubleshooting process a lot longer. Time is ephemeral, the Earth makes a bad clock, and mammals are diurnal. Those 3 things make clocks and time-keeping a 'hands on' job.



I miss falsehoods about pathnames:

* That there's never a \0 in a pathname

wchar names on MSWin UNICODE and WinCE. Symbian uses UTF16.

* That paths are seperated by /

Yes, Windows NT accepts /, VMS, VOS, RISC OS also, but MacOS classic had :, and VMS uses []. And there are still \ pathseps only, like DOS, OS/2, SYMBIAN, Novell NETWARE, AmigaOS4. Native Acorn RISC OS uses . as pathsep and : as in DOS.

Just the easiest ones.


"* That paths are seperated by /" The day I learnded that Korean Windows version uses a Won sign and Japanes use a Yen sign was very bad day.


AmigaOS paths are separated with "/" between directory elements, not "\", but with a volume name separate from the path name with a ":", similar to Windows.

But what makes matters more complicated, is that on AmigaOS "/" is equivalent to "." on Unix systems, and "//" equivalent to "..", and "."/".." are legal filenames. AmigaOS doesn't have an equivalent to "/" in Unix (everything is rooted in a volume, and there are many volumes), but ":" can be used to prefix a path to make it relative to the root of the current volume...

It breaks all kinds of assumptions people make..


And because time is so simple, we figured to just rely on accurate time for TLS certificate validation and thus the security of HTTPS. </sarcasm>


Many, if not most of these things are problems with the environment, not things programmers should think about or try to solve. In fact, most of them should explicitly not be thought about. All that that will do is lead to defensive programming - What if X happens? What if Y? The answer to most of them is simple - Crash. Make it loud and clear that something is wrong. Any attempts to rectify the problem, and most attempts to even detect it will only add surface area to the code, surface area where you can screw up and introduce bugs.

Could the system's timezone change? Yes. If you're manipulating time sanely, you're already using a timezone aware time class - particularly when serializing - and that's great. But if you're uncertain, it's best not to try to rectify. Your program will never be able to guess with any success.

Almost all of this post strikes me as along the vein of the questions of Babbage - "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" Almost all of these are the wrong numbers. Rather than leading you to the simple, correct solution (Use good serialization formats and timezone aware datastructures) it leads you down a path of paranoia, convinced the world is out to get you. If you're programming for that world, you're either a DRM programmer and should burn in hell, or you're doing it wrong. Trust your environment and OS and make damn sure that when you're setting up those layers you set them up right - Don't worry that every second open() call will return an invalid filehandle, just because.


>Many, if not most of these things are problems with the environment, not things programmers should think about or try to solve. In fact, most of them should explicitly not be thought about. All that that will do is lead to defensive programming - What if X happens? What if Y? The answer to most of them is simple - Crash.

When it comes to time, a crash is not the most likely outcome of not thinking about what could happen. More likely your code will stall or do the wrong thing.

Think about polling, pinging other systems or rate limiting. At the end of daylight savings time your code could easily stall for an hour or DDOS another system because rate limiting fails.


There are situations in which it is not acceptable to make a "loud crash", e.g., while a plane is flying.

There was a quote by a nasa engineer that an incorrect action is better than no action at all, but I cant find it at the moment.


I'm pretty sure that if a flight computer detects an inconsistency, it will immediately reboot, and not try to limp along in a bad state. Either the reboot is fast enough to recover quickly enough, or the redundant systems will take over.


No.

Yesterday my friends Mac crashed hard while they were working on a foolishly unsaved one-and-a-half page document in LibreOffice.

At the next start LibreOffice gives a big warning of "Oh shit things are really wrong, should I fix them for you? [Continue | Cancel]" .

Thank you LibreOffice team for making it so that within the time of a phone call to me plus the time it took to press "Continue" they were able to recover the their document and continue working.

This "attempt to rectify" the problem, could only have made things better not worse, so that's reasonable to implement.

I am not saying that every problem needs a solution like this. But blanket statements like "crash whenever there is a problem with your environment", while certainly the correct way to do it in some cases, leads to software that's really shitty use if that's all the software does.

Because while

> Almost all of these are the wrong numbers.

is correct from a programmers point of view, we aren't talking about the numbers a user put in, but rather numbers that the user has no control about.

And not many things are more annoying than computers doing unexpected things for reasons that are incomprehensible to you.


I don't think parent comment meant ditching swap files in text editors or reboot on GPS errors in plane's autopilot. Just sort out upfront where the value is (user data, safety and reliability, rendering fast, etc…) and set requirements appropriately.

There is no reason to handle leap seconds in a flappy bird game, or fork your database server to implement "proper" time handling with historically correct time zones and all the appropriate conversions between them, if you are writing a Twitter client.


>At the next start LibreOffice gives a big warning of "Oh shit things are really wrong, should I fix them for you? [Continue | Cancel]" .

> Thank you LibreOffice team for making it so that within the time of a phone call to me plus the time it took to press "Continue" they were able to recover the their document and continue working.

Uh, that's exactly what the OP was advocating, if I understand correctly. On a consistency check failure (i.e. an assert), crash immediately [1]. If the application correctly handle transactional state changes, it will be able to recover on startup from the replay log, as all changes are immediately persisted on the log.

This approach is known as "Crash Only Software", and it is pretty much the only approach for writing robust applications.

[1] Syncing the replay log to stable storage can be a good thing though.


Yes, and I'm consistently disappointed that HN no longer gets this - It's becoming an echo chamber of those who can't and won't, rather than those who architect and learn. Timekeeping considerations are rarely-to-never the responsibility of an application programmer, and the scenarios presented - Leap seconds, etc - Are either meaningless (Who cares if your delta-t value is off by a second over a three month report?) or incredibly meaningful to the point you explicitly define them in the spec (High-freqeuncy trading systems should use good linearization mechanisms, not just rely on 'timestamp' - The programmers who are working on these problems have well documented that these are hard problems that throwing more time specificity bits doesn't solve).

High level talks about low-level concerns are rarely helpful. This overview of detailed problems without links or even understanding of the relevant literature (It doesn't even mention the scenario that time runs backwards, which is way more common and terrible than pretty much anything on the list). This was a bad post, and it's bad training - Bringing up superficial questions without giving places to check answers for sanity. Many people will likely think about these issues halfheartedly, form half-baked answers, and propagate mistakes. Good learning not only asks questions, but asks follow ups and helps reach complete solutions.


Yes. To further play devil's advocate; a lot of times it's better to just write time handling in a naive manner. Even if you know it will fail under certain circumstances, the program might not need to always be correct to be successful. I HATE writing stuff like this, but sometimes the ROI is just not there.


Yeah, same thing I was thinking. Being exact in time can drive you crazy. Don't run yourself in the ground.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: