8 ms·
Store epoch times as 64-bit floats
- sposeray 3y ago[dead]
- deleted 3y ago[deleted]
- not2b 3y ago64 bit integers are just as cheap, and that's where everyone is going.
- mungoman2 3y agoYeah this doesn't hold water. If you need the precision, float isn't suitable since he precision drops of. If you don't need the precision, no need to use float. Just use int64.
- dragontamer 3y ago> int64 I'll go one step further. Time should be represented as unsigned integers, while time-differences should be represented as signed integers. "10 minutes ago" is int64. June 9th 2023 should be unsigned integer64.
- dontlaugh 3y agoThat doesn’t work, since it can’t represent dates before the epoch.
- Kilenaitor 3y agoWait if you just need dates, why not store dates? I was under impression unixtime is best for timestamps. But no reason to store something like a birthday using them; just do a string YYYY-MM-DD?
- WalterBright 3y agoBecause of daylight savings time and time zones.
- dragontamer 3y agoPostgres's time handling types are elaborate, and probably the best I've personally worked with. Timestamp with TimeZone (including DST + timezone offset) is a different type from timestamp without TimeZone (ie: normalized to GMT). Timestamp - Timestamp results in "interval". Perhaps my method I was discussing doesn't work. But the overall idea that "Timestamp" needs to be a different type than "Interval", is pretty key IMO to handling date/times appropriately.
- hfkwer 3y agoSame in C#. DateTime, DateTimeOffset, TimeSpan.
- WalterBright 3y agoEverybody has this painful urge to reinvent the trivial in an incompatible way.
- WalterBright 3y ago> is pretty key IMO to A time_t can handle intervals just fine. time_t interval = t1 - t0;
- dragontamer 3y agotime_t will not handle daylight savings time conversions like Postgresql does. Unambiguously resolving "Timestamp at Eastern Time - Timestamp at Arizona Time" is not as simple as you might think. Postgresql handles this case. Trying to make "time_t" handle all cases is a mistake. We need like 3 to 4 types at a minimum to handle all of the edge cases that occur in the real world. (And if anyone teaches me of any more complications, maybe we'll need even more types)
- duskwuff 3y ago> Time should be represented as unsigned integers Why artificially limit yourself to only representing times after the epoch? It's not like an extra bit of range is going to make or break anything.
- uoaei 3y agoAdding one extra bit doubles the time horizon...
- zamadatix 3y agoSure but 1970 (or 1899 or 1582 or whatever) is a hell of a lot closer than 2^63 or what have you so why double the end already ridiculously far away instead of the one extremely close?
- uoaei 3y agoi32 is used for Unix time, resulting in overflow sometime in 2038. If that was changed to u32, overflow would happen instead in 2106. 15 years is close enough that such a change would actually "make or break" timekeeping on human timescales. Using i64 for nanoseconds with the same origin (1970-01-01), we could cover roughly 1677-2262. Using u64 for nanoseconds we could cover roughly 1970-2554, or more generally about 585 years of timestamps from wherever a new proposed origin would be. Likely we don't need nanoscale precision for times far enough in the past, so I guess "far enough" is the definition worth arguing over here.
- zamadatix 3y agoYou're looking far out for 2106 while ignoring the signing change already broke all date calculation from prior to the epoch. This means, with an unsigned version, you start out immediately butted against the problem that many real dates are not representable instead of running into this problem many years away. The advantage that future dates will be representable twice as far out doesn't make up for being butted up against the same problem in the other direction from the start. The same story is present with 64 bit nanosecond based timestamps, albeit we're keeping the mid date ever so slightly in the past for ease of conversion. If dates in 2264+ are important then just use a 128 bit timestamp, it'll fix the problem for many multiples the age of the universe instead of causing issues now to gain a few hundred years of padding in the future. Another common approach is to keep u64 second based timestamps and save the nanoseconds as another integer. This comes at the cost of "only" solving the problem for hundreds of billions of years but being interchangeable with those using non-fractional timestamps.
- Tuna-Fish 3y agoNo, because times before 1970 exist. With signed timestamps, you have to figure out weird ways to represent when you need to talk about times in the past, with signed 64-bit timestamps you can represent any moment since well before big bang.
- booi 3y ago> times before 1970 exist mmm I don’t think that’s true. - your computer
- deleted 3y ago[deleted]
- layer8 3y agoIf you use signed int64 to represent differences, then in order to be able to represent all possible differences, timestamps need to be restricted to a 63-bit range. Might as well use a signed int64 restricted to nonnegative numbers as an uint63, or restricted to 62 bits of each negative and nonnegative numbers as an int63. Alternatively, you’d need an int65.
- NoMoreNicksLeft 3y agoThere are reasons to want pre-1070 dates. I need signed.
- lelanthran 3y ago> Time should be represented as unsigned integers, while time-differences should be represented as signed integers. > "10 minutes ago" is int64. June 9th 2023 should be unsigned integer64. Won't you run into problems with trying to turn "ten minutes before 1970" into a time? IOW, if you subtract two `time` types, the result must be a valid `time` type, so you can add/subtract to it. The result cannot be a `timediff` type.
- feoren 3y ago> if you subtract two `time` types, the result must be a valid `time` type, so you can add/subtract to it. The result cannot be a `timediff` type. Huh? Of course `time` - `time` gives a `timediff` type. You can add/subtract to it: you add/subtract timediffs, or you can add/subtract a timediff to/from a time. Why would you ever be directly adding times? What is 100 AD + 100 AD? 200 AD? Not if you pick a different 0-point for your calendar ...
- Gibbon1 3y agoAs an aside dang would probably ban my account if I let rip about what I think about hardware engineers designing real time clocks that count time in HH:MM:SS + day/month/two digit year. And 100 or 128 hz subseconds. But yeah started using int64 30 years ago and all the fuckedness went away.
- marcosdumay 3y agoYeah, with 64 bits we can go into 1/32768 of second precision and still not get any problem.
- fredoralive 3y agoI suspect the hardware engineer would explain the great favour he’s doing you by handling all the handling of all the weird splits between things like hours, minutes and days for you in hardware logic, rather than you having to waste previous cycles of your MCU’s core to do that sort of thing. But it is indeed a real pain when you want dates in more abstract than human forms…
- JohnFen 3y agoYeah, that hardware engineer isn't really doing anyone any favors.
- JdeBP 3y agoThe rest of us, including a number of hardware engineers who have learned from history, would point to the real-time clock chip that did hardware rules for things right for only one country for a mere three years in the 1980s, until the legislation changed, and whose behaviour has been wrong ever since. Step forward the MC146818, used in the PC/AT and emulated by chipsets since, whose built-in daylight savings time change rule implemented in hardware was rendered obsolete in 1987. http://catless.ncl.ac.uk./Risks/24.60.html#subj12.1 http://catless.ncl.ac.uk./Risks/24.60.html#subj12.1
- Gibbon1 3y agoOld electrical engineer I worked under in the 1980's mentioned he designed a clock calendar STD Bus card. Next design he replaced the whole thing with a 32 bit counter on the processor card and 250 bytes of Z80 assembly. Unrelated I think the lobbyists that got daylight savings time changed charged the BBQ manufacturers $50k.
- KMag 3y agoI remember one colleague concerned with casting a Java 64-bit millisecond timestamp to double seconds when crossing languages (over to a somewhat TypeScript-like financial modeling DSL developed in the mid-late 1990s, where it's a bit clunky to deal with numbers in any format other than doubles). I added a comment apologizing to software archaeologists on 12 October 287,396 C.E., when the precision of double timestamps (with 1970-01-01T00:00:00 UTC epoch) drops to 2 milliseconds, and the reviewer was fine after that.
- snailtrail 3y agoPosting blog like this how you get rejected from your dream job.
- cassepipe 3y agoCare to elaborate ?
- KaiserPro 3y agoI think they are implying that storing time as a float is riddled with problems (like arithmetic needs to think about hardware bugs and implementations) The problem being that OP kinda glosses over them.
- lordnacho 3y agoThink he's saying the advice in the blog post is bad.
- cassepipe 3y agoWould have liked to know why though. Oh well.
- jbay808 3y agoI strongly disagree with this. It only makes sense to use floats if you want time to have increasing precision the closer you get to 1970. From a symmetry group perspective, that makes no sense; the amount you care about the incremental precision of time measurement is invariant with respect to the present date. (Translation invariance). This means you want uniformly distributed time samples, hence an integer format. If you think microsecond precision is good enough for anybody, then you could consider using an integer where the LSB represents 1 microsecond. But don't use floating point time, unless your specific application cares more about time scale invariance than time translation invariance.
- dheera 3y agoYou can even go to nanosecond. The largest uint64 is 18446744073709551615 and epoch time now in nanoseconds is less than a tenth of that i.e. 1686340765688397824 You can go for another 500+ years safely on nanoseconds-as-uint64. I fully disagree with using float64. It wastes bits on an exponent and you cannot safely use == to compare timestamps that have math done on them or have been converted to/from a string (including e.g. sent as part of a JSON).
- lordnacho 3y agoMe too. I thought it was normal already to just store the unix nanos. At least that's what I do and it seems to work. Yes I have stuff with nano granularity. You don't want to get into floating point, it gets all fuzzy and then when you need to change it, there's a bunch of code to change.
- johnea 3y agoThe article fails to mention the earliest standard addressing this issue, DJB's taitime: https://cr.yp.to/proto/utctai.html https://cr.yp.to/proto/utctai.html
- deadmutex 3y agoint64 to represent times before 1970, and to make it easier to do time diffs (since subtracting two uint64s in C++ can cause overflow)
- WalterBright 3y agoI think it was Microsoft BASIC that stored time as a floating point number. What a bad idea. Converting from it to an integer and then converting back to float would cause the time to "drift" due to rounding errors. It's the same reason why you should never use floating point numbers for account balances.
- adzm 3y agoThe VARIANT date type uses a floating point number; the whole number portion is the day (days past 1900 January 1) and the fractional part is the time. Not sure about classic BASIC; I don't really recall there being a specific time type, though I know later things like Visual Basic and etc would just use the VARIANT date type above with a 0 day component. I like Windows' FILETIME which stores time as 100-nanosecond intervals since the beginning of the year 1601. C#'s DateTime is similar but uses an epoch of 0001 January 1. I know JavaScript and others simply use the usual unix Epoch but with milliseconds rather than seconds, so time() * 1000.
- eyelidlessness 3y agoI don’t know why but this just reminded me of how I discovered that SQL Server stores times in increments of .000, .003, .007 seconds. I wasn’t even using SQL Server (directly), just trying to understand what looked like data corruption as an API consumer. That discovery was a precursor to probably the second worst six-month stretch of my entire life (this one was caused by mishandling of time zones, and not the fault of SQL Server, but the previous experience helped me identify the issue).
- evil-olive 3y agoyeah...no. don't use floats for this. int64 "nanoseconds since the epoch" seems to be emerging as the de facto standard. used in Golang [0] and adopted by Python starting in 3.7 [1] that PEP also spells out some of the problems with using a float64: > The Python time.time() function returns the current time as a floating-point number which is usually a 64-bit binary floating-point number (in the IEEE 754 format). > The problem is that the float type starts to lose nanoseconds after 104 days. Converting from nanoseconds (int) to seconds (float) and then back to nanoseconds (int) to check if conversions lose precision: 0: https://pkg.go.dev/time#Time https://pkg.go.dev/time#Time 1: https://peps.python.org/pep-0564/ https://peps.python.org/pep-0564/
- EdSchouten 3y agoAs far as I know, Go uses year 1 instead of 1970 as its epoch.
- bjornsing 3y ago> Even through the 90s, long after many system calls became formalized, floating point math was much more expensive than integer math. IIRC the main reason floating point numbers weren’t used in system calls back in the 90-ties was that kernel code couldn’t use the CPUs floating point registers, or they would have to be saved at the entry point of each system call and restored before returning to user space. This was deemed too expensive.
- benmmurphy 3y agoswift has TimeInterval which is a double and can hold an epoch offset. https://developer.apple.com/documentation/foundation/timeinterval https://developer.apple.com/documentation/foundation/timeint...
- happytoexplain 3y agoYes, but it's just a typealias intended to represent a span of time in APIs. As the docs say, "On its own, a time interval does not specify a unique point in time, or even a span between specific times."
- Someone 3y agoThat type wasn’t invented by the swift standard library writers; it’s a 1:1 copy of Objective-C’s NSTimeInterval (https://developer.apple.com/documentation/foundation/nstimeinterval https://developer.apple.com/documentation/foundation/nstimei...), so it’s not necessarily what a modern language designer would pick.
- gumby 3y agoGreat choice! Far away points in time will be less precise, but really: how good is anyone at predicting the future anyway? (in other words a terrible choice, though not for the reason above).
- ClumsyPilot 3y agoUse 128 bit integer in femptoseconds, with epoch being the begining of the universe. And it should be signed, because what if there was a previous universe. Jokes aside, Unix Epoch shouls be replaced by Tai time on every computer. https://en.m.wikipedia.org/wiki/International_Atomic_Time https://en.m.wikipedia.org/wiki/International_Atomic_Time
- well_actulily 3y agoThat gets us to ~5.392 * 10ˆ15 years after the Big Bang, which doesn't nearly get you to the heat death of the universe ~1.7 * 10ˆ106 years from now, but is probably good enough.
- jjoonathan 3y agoBlack hole farmers hate this.
- mihaic 3y agoThe person that pushed for the leap second should be flogged very hard!
- erik_seaberg 3y agoNo, he might be into that.
- halosghost 3y agoIf we're going to go this far, why not go all the way? [1] I.e., use a 536-bit unsigned integer to store Planck time with one Planck time following the big bang as the epoch, and use the top three bits as a tetration height instead of an exponent, and you can get real far. All the best, [1] https://halosgho.st/blog/planck/ https://halosgho.st/blog/planck/
- cyann 3y agoAt first glance I thought you were talking about "Thai" time, which is a surprising calendar when you have dates with years in the 2500 range. Looking at you Symantec AntiVirus, storing AV definitions date using the user's locale... https://en.wikipedia.org/wiki/Buddhist_calendar https://en.wikipedia.org/wiki/Buddhist_calendar
- gumby 3y agoFrom the post: > Why am I not using float64 time already??? [fp used ot be slow and was not standardized, but it got faster and after a while you could count on having IEEE-754] This is not the reason. Until IEEE-754 fp was terrible. As in buggy terrible. It took years of pain to learn how to get it right. And you can see this in the standard: it's a very short standard, super easy to understand, trivial, really...if you ignore the enormous amount explanations, corner cases, special cases, surprising symmetries, and other copious testament to the well-meaning Mistakes that Were Made in the years before. Intel provided a ton of trade secret understanding from the mistakes in the 8087, and UCB maths prof was intimately involved. It's an incredible achievement. The history of the standard is quite exciting but has been covered on HN several times before.
- theandrewbailey 3y agoThis would have been a good April Fools joke.
- pphysch 3y agoThey meant to post it at 04-01, but posted it at 02-01 instead to prove that precise timing doesn't matter
- shpx 3y agoLet's store time as integer Planck times since the Big Bang. 256 bits ought to be enough for anybody.
- johnea 3y agoThe article fails to mention the earliest standard addressing this issue, DJB's taitime: https://cr.yp.to/proto/utctai.html https://cr.yp.to/proto/utctai.html
- johnklos 3y agoNah. I think we should move to 500 bit times. That'll give us the Planck time resolution from the Big Bang through the heat death of the universe.
- Szpadel 3y agoon February 25, 1991 American Patriot Missile battery in Dhara failed to track incoming missile because they used floating point time instead of integers. 28 dead 100 injured time precision was decreasing with time since system was booted and after about 100h of operation this accumulated enough to system believe that incoming missile is already unreachable using existing calculations and caused it to not react at all I think that is great example why changing precision depending on time might be very bad idea. imagine that afer Y2038 that slight drop in precision would cause some critical system to fail in unexpected way
- CamperBob2 3y agoThe point is, double precision fixes this for timescales within reach of human existence. A 24 bit mantissa isn't enough for anybody. A 53-bit mantissa is enough unless you need +/- one nanosecond precision at 100 days. If you need that -- and some people do -- your application is too exotic to influence the standards that apply to everyone else.
- deafpolygon 3y agoReal chad developers use string.
- deafpolygon 3y agoAre you not entertained?
- binkHN 3y agoFWIW, Java does this with a long and an int: https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html https://docs.oracle.com/javase/8/docs/api/java/time/Instant....
- wood_spirit 3y agoUUIDv7 is a good way to store time in UUIDs. See https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-01.html https://www.ietf.org/archive/id/draft-peabody-dispatch-new-u...
- _kst_ 3y agoUUIDv7 uses a 36-bit unsigned field to represent seconds since 1970-01-01 (and optionally other fields to enable sub-second precision). It doesn't overflow until the year 4147 -- but since it's unsigned it can't represent times before 1970. It's not designed to store times in the past, so that's not an issue for its intended use, but using it as a general time representation format could be problematic (say, if you want to represent a person's birth date). (An aside: At a previous job, I worked on some code that would display a person's age given their stored birth date. The code didn't handle dates before 1900. I did a little research and found that that wouldn't be a problem, since everyone born before 1900 is dead. Ten years earlier, it would have been an issue.)
- junon 3y agoNo thanks. For one, hashing becomes ambiguous. Under no circumstances are NaN and NaN equal to each other. That will cause mayhem in any system looking for an iota of resiliency.
- loxias 3y agoI might be missing something but is this actually arguing for blindly and naively taking time-since-epoch as fp value and then think of the smallest (which would change over time!) possible epsilon?? Disappointing to me how visually appealing this site is for how useless the words/idea themselves are.
- _kst_ 3y agoFloating-point time loses the ability to represent milliseconds, microseconds, and nanoseconds exactly. C already has (since the 2011 standard) `struct timespec`, a structure consisting of a `time_t` representing seconds since the epoch (typically 64 bits signed) and a `long` representing nanoseconds. It's admittedly awkward for arithmetic, but it doesn't overflow for another 292 billion years. It gives about 200 times better precision than 64-bit floating-point (for the interval from 2004 to 2038). 32-bit signed time_t is still a problem, particularly for embedded systems that are difficult to update. (A lot of such systems probably don't need to know the current time.) A 64-bit signed integer representing nanoseconds since the epoch doesn't overflow until 2554. Floating-point time is likely to be good enough in a lot of contexts -- but the fact that it's non-standard, unlike `time_t` and `struct timespec`, is a big disadvantage.
- JdeBP 3y agoMeasuring time as a combination of time_t and a fraction of a second count goes back far longer than that. 4.3BSD had time_t plus microseconds, for example.
- JdeBP 3y agoIt's saddening to see the number of people who critique the idea of storing time as an unsigned integer by immediately responding that that means that times before 1970 cannot exist. This bespeaks a continuing poor knowledge of the subject, despite all of the "falsehoods that programmers believe about" documentation that has grown up. * https://github.com/kdeldycke/awesome-falsehood#dates-and-time https://github.com/kdeldycke/awesome-falsehood#dates-and-tim... Microsoft, for one example, has been modelling times as a 64-bit unsigned 100-nanosecond count since 1601 (proleptic-Gregorian proleptic-UTC) for about 30 years, now. * https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime https://learn.microsoft.com/en-us/windows/win32/api/minwinba... Daniel J. Bernstein in the late 1990s chose a 0 point for an unsigned count so far back that it pre-dates most estimates of the point of the Big Bang. * http://cr.yp.to/libtai/tai64.html http://cr.yp.to/libtai/tai64.html 1970 is not the mandatory origin for every timescale. (Indeed, in the early years of Unix itself there wasn't even a stable origin for time.) It is not a valid reason for dismissing the idea of storing time as an unsigned integer. It's also sad to note that the headlined page's first sentence has one of the very falsehoods that programmers believe about time in it.
- foobarbazetc 3y agoNah. uint64. The end.
- perilunar 3y agoI made a universal timeline[0] that scales from milliseconds to "all of time", and for various reasons I store the time as years BC/AD in JS floats (64 bits). It goes to 2^1024, or approximately 1.7977e+308 years. Not the most efficient, since all the numbers < -13.8e9 are wasted, but it means the raw number matches how we commonly talk about deep time. (Historical dates are stored as an ISO-8601 string and converted). 0. https://timepasses.net https://timepasses.net
- Const-me 3y agoI think Microsoft did it better back in 1993. They’re also using 64-bit numbers for datetime, but these numbers are integers, expressed in 100 nanoseconds ticks. That representation is used in NTFS, other components of Windows kernel and userland, .NET runtime including the modern Linux-running version, and quite a few other places. Y2038 is a non-problem, the representable range is about ±29000 years around the epoch. The extinction of the dinosaurs is not representable, but I think it’s OK in practice, only a small minority of software needs dates that far in the past or future. Accuracy is 2.5 times better than FP64, and is equal over the complete range.