Reputation: 2945
Is there any C++ implementation of 64-bit Unix timestamp conversions for 32-bit systems? I need to convert struct tm
to 64-bit integer and vice versa, including leap years, time zones, UTC. Also need it portable, at least for GNU/Linux and Windows.
Upvotes: 12
Views: 20689
Reputation: 41992
64-bit time support on 32-bit Linux was first introduced in the 5.1 kernel with the addition of the new *time64
syscalls (because changing the return type of old system calls breaks old applications). Check this table and you'll see that those syscalls are only available on 32-bit platforms.
But that's only support from the kernel side. You can call clock_gettime64
directly (from inline assembly, or from C with syscall()
function) to get the current time but you'll need Linux-specific code because there's no glibc support yet. For full userspace support you must be on Linux 5.6 or higher along with musl 1.2+ or glibc 2.32+. Just rebuild your code and time_t
will become 64-bit long. Now code that uses time_t
will become completely portable
All user space must be compiled with a 64-bit
time_t
, which will be supported in the coming musl-1.2 and glibc-2.32 releases, along with installed kernel headers from linux-5.6 or higher.Applications that use the system call interfaces directly need to be ported to use the
time64
syscalls added in linux-5.1 in place of the existing system calls. This impacts most users offutex()
andseccomp()
as well as programming languages that have their own runtime environment not based on libc.
That said, even if you're on newer glibc then you may still need to build your own libs in various situations as Debian said while they're transitioning
glibc 2.34 provides support for both the existing 32-bit ABI/API and a new 64-bit ABI/API. However it does not provide a switch forcing use of the new API/ABI - each build/package chooses explicitly to use the 64bit API/ABI (by setting
_TIME_BITS=64
). This is a problem for Debian as in a normal transition we expect that simply building against the new library will get you the new ABI. Something (glibc, dpkg, gcc?) has to say 'use 64-bit time by default'. 1030159 has implemented aDEB_BUILD_OPTIONS=abi=+time64
option as a consistent Debian mechanism.
For more information read
Upvotes: 0
Reputation: 2395
You need:
typedef long long time64_t;
time64_t mktime64(struct tm *t);
struct tm* localtime64_r(const time64_t* t, struct tm* p);
Originally (in 2011) this answer contained links to 2038bug.com where it was possible to download the small pivotal_gmtime_r
library, containing the mentioned functions. The library has been removed from 2038bug.com back then, the links became broken and were removed from the answer by a moderator. Seems like that pivotal_gmtime_r
code can now be found here:
https://github.com/franklin373/mortage/tree/master/time_pivotal
Also, I've found another, more recent library, called y2038
, that also implements mktime64
and localtime64_r
:
https://github.com/evalEmpire/y2038
Upvotes: 14
Reputation: 9
Yeah use stuct tm *_localtime64 ( const __time64_t *timer);
That's if your windows fan.
Upvotes: -1
Reputation: 67502
You seem to be making the assumption that time_t
is 32-bits on 32-bit systems, and this may or may not be true.
On Windows, starting with Visual Studio 2005 the size of time_t
is 64-bits, even when you compile for 32-bit Windows.
The unfortunate part is that glibc defines it as long int
, which on 32-bit systems is a 32-bit integer. That means that 32-bit Linux and other 32-bit platforms that are based on gcc/glibc (like Cygwin) will not be able to work with 64-bit timestamps.
If your application must run on 32-bit glibc, then you should use your own conversion functions, which could be the same functions in the C library recompiled to use 64-bit timestamps.
If you need source code with a permissive license (BSD), then you can look at these functions in minix3. Here is localtime. The source is hyperlinked, so you can find the others easily.
Upvotes: 6
Reputation: 1
The function converting a struct tm*
to a time_t
is mktime
. You can find many implementations of it, eg. in Glibc and in libvxc's mktime.c
file. You could take the code (assuming it is legal to you, so please respect licenses) and change time_t
to some 64 bits integer like int64_t
.
The functions doing the other conversions from time_t
to struct tm*
are localtime
or gmtime
and you could do likewise.
However, you might have a more fundamental issue: your 32 bits machine running in the year 2040 should have some way of giving you the current time (as the time
system call does) appropriately in the 64 bits variant of time_t
, and that is much harder (it depends upon the kernel and the hardware).
Upvotes: 7