Just use int64.
Just use 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.
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?
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.
A time_t can handle intervals just fine.
time_t interval = t1 - t0;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)
Do conversions to/from local time only as a first and last step.
It's the only sane way to do it. The D runtime library does that, and it has proven to be robust and sane. We're also recommending that users do the same thing with different character representations - do all calculation and processing in UTF-8. Other sets are translated upon input into UTF-8, and the UTF-8 is translated to other character sets only on output.
Cool.
Now how do you enforce that? Spoiler: have the local-time be reported as a TimestampWithTimeZone.
When you're doing calculations, make them all Timestamps.
When you're done, you can remember that you've converted from internal UTC-timestamps into the proper output format because you'll have a TimestampWithTimezone again.
-----------
We're programmers. We have problems that are simple and enforceable through compiler constructs called "The Type System".
Why have the human figure out if they have time-zone back-and-forth correctly or otherwise made a mistake (ex: adding code to the wrong "part of the process" and accidentally mucking with a TimestampWithTimeZone input/output variable rather than the internal Timestamp-UTC-only type variables?)
Just... leave the job of checking this entire process to the compiler. If your n00b coworker messes up, the type system catches it and we're all set.
UNIX timestamps have no timezones. They are just the number of actual seconds that have elapsed since a certain commonly-agreed time. You measure the number of seconds between two events just by subtracting their timestamps arithmetically, and don't need to do any parsing or interpreting of timezones. You can just say "this hacker in Russia breached the firewall 35 seconds after this dev committed code in the US" just by subtracting two numbers.
The time an airplane takes off, the time your firewall detected a security event, the time a cross-timezone meeting starts, these are all good to store as UNIX timestamps.
Birthdays are different because they are inherently imprecise; humans tend to celebrate their birthdays when it's a certain day of the month in their local time zone, with little to no regard for the time zone they were born in. Someone born in Singapore (UTC+8) and lives in Alaska (UTC-8) might still celebrate their 30th birthday on the month and day of their birthday in Alaska time even though their body might need another 16 hours before it has technically experienced 30 years of life.
If only. UNIX mishandling of leap seconds makes this all a illusion, in reality you need to have logic to handle them
So yes, you have to handle leap seconds when you're converting from the timestamp to/from the time scheme you are interested in, just as you have to handle leap years, etc. The UNIX timestamp is just a different way of marking time, and is blessed with not worrying at all about how that time relates to the actual motion of the Earth. That makes it easy and consistent for common operations. It is not mishandling anything. It just can't shield you from the complexity of the forms of timekeeping that make it a point to be synchronized with the Earth.
Nope. UNIX timestamp is days since epoch × 86400 + seconds since midnight. And that is the crux of the issue.
Are you perhaps confusing that with the standard algorithms for converting between Unix time and "human" time? Because what you say isn't wrong for that case, and this is a classic trap for new players:
"A Coordinated Universal Time name (specified in terms of seconds (tm_sec), minutes (tm_min), hours (tm_hour), days since January 1 of the year (tm_yday), and calendar year minus 1900 (tm_year)) is related to a time represented as seconds since the Epoch, according to the expression below.
If the year is <1970 or the value is negative, the relationship is undefined. If the year is >=1970 and the value is non-negative, the value is related to a Coordinated Universal Time name according to the C-language expression, where tm_sec, tm_min, tm_hour, tm_yday, and tm_year are all integer types:
tm_sec + tm_min60 + tm_hour3600 + tm_yday86400 + (tm_year-70)31536000 + ((tm_year-69)/4)86400 - ((tm_year-1)/100)86400 + ((tm_year+299)/400)*86400"
(Quotes from https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1...)
Moreover, if the units you are referring to are "seconds" then the statement "[t]he UNIX timestamp is literally the count of units past the epoch" is also wrong. If not, what are the units here?
> That's not true. Unix time is specifically defined as "A value that approximates the number of seconds that have elapsed since the Epoch."
It's missing 27 seconds that elapsed since the epoch. (Plus whatever happened with rubber seconds before 1972). Maybe that fits within the definition of approximate.
But if you need to record events that happen on a leap second or the second before a leap second, unixtime is unhelpful.
If you want to record a duration that includes a leapseconds, unixtime is unhelpful, although if the duration is long enough, the difference may be of no consequence.
Mail an atomic clock easy to west, and a different one west to east, and they'll drift different amounts. Put one in a plane, it will disagree with one on the ground. Put one on a mountain, it will disagree with one at sea level. Put one at the pole, it will differ with one on the equator.
There is little sense in claiming one time is exactly equal to another. Close to some tolerance is useful.
I'm struggling to think of a context where we basically want to create timestamps for things that happened in the past. Especially things that we want to dynamically localize rather than e.g. just store as a straight up timestamped string.
Nobody's really solved this, it has to be tackled anew for each case of "comparing dates from long ago".
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.
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.
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.
For example, the unix epoch can safely be 1970 because the operating system did not exist prior to 1970, so there's no real-world situation in which you'd be time-stamping a system event or log entry prior to 1970.
That said, time_t is usually a signed type in C. There are several reasonable historical explanations for that though, including the need to use -1 for an error return, and the fact that unsigned ints weren't present in C until 1978.
The Unix epoch was never an issue being 1970 because they knew they were making it as signed, not because they thought Unix systems would never deal with e.g. files from before Unix was created.
As far as I've ever read, negative unix timestamp values generally were not used. Since -1 was used as an error value, you cannot safely determine whether that value represents an error vs a legitimate timestamp one second before the epoch.
I'm not familiar with if/how early versions of Unix were able to interact with non-Unix files/filesystems, but I doubt they would preserve metadata such as mtime if so.
mmm I don’t think that’s true.
- your computer
Alternatively, you’d need an int65.
> "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.
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 ...
But yeah started using int64 30 years ago and all the fuckedness went away.
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.
Unrelated I think the lobbyists that got daylight savings time changed charged the BBQ manufacturers $50k.