4 ms·
The C standard does not require time_t to be signed (nor does POSIX). Just changing the 32-bit type to unsigned would (in some senses) extend the lifetime of t
by loeg 2y ago
The C standard does not require time_t to be signed (nor does POSIX). Just changing the 32-bit type to unsigned would (in some senses) extend the lifetime of the type out to 2106. You could at least avoid some classes of ABI breakage in this way. (On the other hand, Glibc has explicitly documented that its time_t is always signed. So they do not have this option.)
- account42 2y agoAh yes, let's introduce subtle bugs or code that calculates the difference between two time_t's where the result can be negative. If something is effectively always signed you can assume that things depend on it being signed even if the standard doesn't guarantee it. If you are building a Linux distribution you can't just handwave such code away as "technically it was already broken on this theoretical POSIX compliant platform that no one uses".
- deleted 2y ago[deleted]
- School-Cotton 2y agoYou would then lose the ability to represent times before Jan. 1st, 1970. Which is not just a theoretical concern; those times appear e.g. in databases with people's date of birth.
- nobluster 2y agoAnd a signed 32 bit time_t with an epoch of 1970 cannot represent dates before 1902. Using time_t to store legacy dates is not advisable - even if you ignore all the issues with time zones and changing local laws pertaining to offsets from UTC and daylight saving time.
- pwg 2y agoWhile true, that limitation has always existed, so everyone has already implemented whatever was necessary to represent dates earlier than that. Changing 32-bit time_t to unsigned suddenly makes all dates from 1902 to Jan 1 1970 which were stored using time_t (even if it was non-advisable, it still will have occurred) appear to teleport into the future beyond 2038.
- cryptonector 2y agoThat's alright, see, because I have no filesystems, no tarballs, no backups, no files on any kind of media with timestamps before 1970, and indeed, no one can except by manually setting those timestamps -- and why bother doing that?! So any pre-1970 32-bit signed timestamps will be in... not spreadsheets, in what? In databases? No, not either. So in some sort of documents, so software consuming those will need fixing, but we're not going to see much teleporting of 1902-1970 timestamps to 2038-2106. I'm not concerned.
- jasomill 2y agoMany important software projects predate UNIX. Perhaps you want to create a Git repository for one of them, with historically accurate commit timestamps?
- loeg 2y agoGit represents timestamps in ASCII strings, like "12345." Not time_t. (I am not sure if it even allows negative integers in this format.)
- jasomill 2y agoI was just using Git as an example of an application where pre-1970 timestamps could be useful. But as it turns out, $ git commit -m foo --date='1969-12-31 00:00:00' [main 25b6e63] foo Date: Sun Dec 30 23:00:00 2012 -0500 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bar
- cryptonector 2y agoWell, Git doesn't seem to set file timestamps when cloning. And as the sibling comment says, Git doesn't use 32-bit signed integers to store timestamps. So this is not a problem. If, however, Git were to some day get an option to set file mtimes and atimes at clone time to the last-modified time of the files based on commit history, then you could always just use a 64-bit system where `time_t` is 64-bit.
- bloak 2y agoSerious question: do people use time_t for representing a date of birth? To me that wouldn't seem right: a date of birth isn't a timestamp and you typically receive it without a corresponding place or time zone so there's no reasonable way to convert it into a timestamp. (The other problem is that a signed 32-bit time_t only goes back to 1901. You might not have to deal with a date of birth before 1901 today, unless you're doing genealogy, of course, but until fairly recently it's something you'd probably want to be able to handle.)
- nomel 2y agoMy birth certificate has location, day, year, hour, and minute of birth. Birth is an event in time, perfectly represented with a (UTC) timestamp.
- Merad 2y agoYour birth is an event that happened at an instant in time, but very few systems concern themselves with that detail. The vast majority need to store birth _date_ and have no interest in the time or location.
- nomel 2y ago> have no interest in the time Setting the bottom couple of bytes to zero achieves this, while maintaining nearly universal consistency with all other events in time that might need to be related with a packing of bits. People do it because it's what's being used at nearly every other level of the stack.
- cryptonector 2y ago> Birth is an event in time, perfectly represented with a (UTC) timestamp. That's not the same thing as `time_t` though. `time_t` is UTC. UTC is not `time_t`.
- School-Cotton 2y ago> Serious question: do people use time_t for representing a date of birth? I have seen people in real life use seconds since the UNIX epoch to represent DOB, yes.
- loeg 2y agoDatabases do not and can not use system time_t. Consider how their on-disk state would be impacted by a change from 32-bit time_t to 64-bit! Instead they use specific or variable size integer types.
- account42 2y agoBroad statements like this are universally untrue.
- cryptonector 2y agoThose databases might not even use `time_t`. It's their problem anyways, not the OS's.
- pezezin 2y agoDoes any database actually use time_t? PostgreSQL uses its own datatype, the number of microseconds since 4713 BC. I am sure that other databases do the same. https://www.postgresql.org/docs/current/datatype-datetime.html https://www.postgresql.org/docs/current/datatype-datetime.ht...
- account42 2y agoHow the timestamps are stored on disk is irrelevant if the code data from those databases ends up using time_t (e.g. because it needs to compare stored timestamps with the current time).
- scheme271 2y agoIf time_t is unsigned, how do times before the unix epoch get represented?
- loeg 2y agoThey don't, much like they already do not. 32-bit time_t has always been finite, and 1970 was a long, long time ago. (See "in some senses" in my earlier comment.)
- pwg 2y agoWhile that avoids 2038 as a "drop dead" date for 32-bit time_t, it also removes the ability to represent any date/time prior to 00:00:00 UTC on 1 January 1970 using 32-bit time_t because you lose the ability to represent negative values. Having all existing stored date/times that are currently prior to the epoch suddenly become dates post 2038 is also not a good scenario.
- loeg 2y ago> it also removes the ability to represent any date/time prior to 00:00:00 UTC on 1 January 1970 using 32-bit time_t Yes, of course. This is probably not the main use of negative values with signed time_t, though -- which is just representing the result of subtraction when the operand happened before the subtrahend. > Having all existing stored date/times that are currently prior to the epoch suddenly become dates post 2038 is also not a good scenario. In practice, there are ~zero of these on systems with 32-bit time_t and a challenging migration path as we approach 2038.
- cryptonector 2y ago> Yes, of course. This is probably not the main use of negative values with signed time_t, though -- which is just representing the result of subtraction when the operand happened before the subtrahend. This is definitely a bigger concern, yes. One has to be very careful with subtraction of timestamps. But to be fair one already had to be very careful before because POSIX doesn't say what the size or signedness of `time_t` is to begin with. Indeed, in POSIX `time_t` can even be `float` or `double`[0]! time_t and clock_t shall be integer or real-floating types. Though on all Unix, BSD, Linux, and any Unix-like systems thankfully `time_t` is always integral. It's really only size and signedness that one has to be careful with. Thus one should always subtract only the smaller value from the larger, and cast the result to a signed integer. And one has to be careful with overflow. Fortunately `difftime()` exists in POSIX. And there's a reason that `difftime()` returns a `double`: to avoid having the caller have to deal with overflows. Basically working safely with `time_t` arithmetic is a real PITA. [0] https://pubs.opengroup.org/onlinepubs/009696799/basedefs/sys/types.h.html
- petee 2y agoOpenbsd did just this for 32bit compat when they changed to 64bit time 12 years ago, and seems to have worked out fine.
- brynet 2y agoNo, time_t is a signed 64-bit type on all architectures, 64-bit architectures have no "32bit compat". https://www.openbsd.org/55.html https://www.openbsd.org/55.html
- petee 2y agoFrom the notes, this is what i was referring to, I think I just mistook the meaning - Parts of the system that could not use 64-bit time_t were converted to use unsigned 32-bit instead, so they are good till the year 2106