All versions before OS X 10.6 "Snow Leopard" have the year 2038 problem. Most installs of 10.6 and all installs of 10.7 "Lion" fixed the main cause of the problem. It's almost gone, but the year 2038 bug might survive in a few apps.
My old PowerPC Mac runs OS X 10.4.11 "Tiger". I went to Date & Time in System Preferences, and tried to enter a date after 2038, but it reset the date to December 31, 2037. It knows that something's wrong in 2038.
OS X is derived from Unix by way of BSD. Apps for OS X use BSD system calls for things like opening files and connecting to the internet. BSD has a long history and some of its system calls come from the 1980s. One of its system calls is
gettimeofday(), which first appeared in 4.1cBSD. UC Berkeley released 4.1cBSD in 1982, more than half a century before 2038. The time from
gettimeofday() is an integer of type
time_t. It counts seconds, where zero is the Unix epoch of 1970-01-01 00:00:00 UTC.
In my old PowerPC Mac,
time_t is a signed 32-bit integer. This causes the year 2038 problem. A signed 32-bit
time_t has a range of -2147483648 to 2147483647. This can only hold times from 1901-12-13 20:45:52 UTC to 2038-01-19 03:14:07 UTC. When this overflows,
gettimeofday() will flip the date from Monday the 19th of January 2038 to Friday the 13th of December 1901.
The fix is to transition from 32-bit
time_t to 64-bit
time_t. For OS X, this transition happened along with another transition from 32-bit pointers to 64-bit pointers, but 64-bit pointers require a 64-bit processor. Apple has only provided 64-bit
time_t for 64-bit processors. It is possible for 32-bit processors to handle 64-bit
time_t, but Apple never provided that feature.
Apple's compilers have supported 64-bit integers on 32-bit processors since OS X 10.0 "Cheetah", when
time_t had 32 bits and
off_t had 64 bits. In Unix and BSD,
off_t is the size of a file, or an entire disk. A 32-bit
off_t would limit OS X to disks under 2 GiB. Apple defined
off_t as 64 bits, so OS X worked with larger disks. Apple defined
time_t as 32 bits in 10.0, so a transition to 64-bit
time_t needed to happen later.
For my old PowerPC Mac, the header file
long. For Intel Mac, the header
<i386/_types.h> does the same. In OS X,
long has the same size as a pointer. So when pointers became 64 bits,
long also became 64 bits, and
time_t also became 64 bits, fixing the main cause of the year 2038 problem.
Apple's 64-Bit Transition Guide says, "Prior to OS X v10.6, all applications that shipped with the operating system were 32-bit applications. Beginning in v10.6, applications that ship with the operating system are generally 64-bit applications." I know from Wikipedia that 10.6 required an Intel processor and 10.7 required a 64-bit Intel processor. A Mac running 10.6 on a 32-bit Intel processor must have had 32-bit apps. I conclude that most Macs running 10.6 and all Macs running 10.7 have 64-bit apps with 64-bit pointers and 64-bit
time_t. Apple released 10.7 in 2011, well before January 2038.
time_t, the year 2038 bug is almost gone, but it might survive in a few apps. Old 32-bit apps might still run on newer systems. Also, 64-bit apps might contain coding mistakes or outdated designs, causing them to convert a 64-bit
time_t to 32 bits. This is a problem for all systems, not only macOS.
There is also Mach time. The kernel of OS X mixes BSD with Mach. Most apps get the time from BSD using
gettimeofday(), but there is a way to go around BSD and get the time from Mach. This is more difficult: the program would call
mach_host_self() to get the host port, then
host_get_clock_service() to get the
CALENDAR_CLOCK, and finally
In my old Mac running 10.4 "Tiger",
<mach/clock_types.h> declares the time as an
unsigned int (inside
struct mach_timespec). This is an unsigned 32-bit integer, with range from 0 to 4294967295, which is from 1970-01-01 00:00:00 UTC to 2106-02-07 06:28:15 UTC. This would exchange the year 2038 problem for the year 2106 problem. It can't reach year 29,940.
I suspect that
host_get_clock_service() was obsolete since 10.0 "Cheetah", because Apple provided faster ways to get the time. These were BSD's
gettimeofday() for calendar time, and Apple's
mach_absolute_time() for monotonic time. The preference for
gettimeofday() put the problem in 2038, not 2106.