The Problem: How Do You Store a Date?
Storing a date like “15 May 2025, 10:30 AM” as a string wastes space, is language-dependent, and is terrible to compare or do maths with. UNIX solved this elegantly: store time as a single integer — the number of seconds since a fixed reference moment.
Keywords in This Post
The Epoch is the fixed reference point that UNIX chose as “time zero”. It is midnight, 1 January 1970, in UTC (Coordinated Universal Time).
Analogy: Think of a highway with kilometre markers. You measure your position from “KM 0” — that starting marker is the Epoch. Your current position (e.g., KM 1,747,123,456) is the number of seconds elapsed. Going back before the marker gives you negative numbers — that’s dates before 1970.
| Date/Event | Seconds since Epoch (approx.) |
|---|---|
| 1 Jan 1970, 00:00:00 UTC | 0 |
| 1 Jan 1971, 00:00:00 UTC | 31,536,000 |
| 1 Jan 2000, 00:00:00 UTC | 946,684,800 |
| 15 May 2025, 00:00:00 UTC | ~1,747,267,200 |
| 19 Jan 2038, 03:14:07 UTC | 2,147,483,647 (MAX for 32-bit signed) |
time_t Data TypeLinux stores calendar time in a variable of type time_t, defined in <time.h>. It is simply an integer type — the number of seconds since the Epoch. You can print it, compare two of them, or subtract one from another.
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t t1 = 0; /* Epoch itself: 1 Jan 1970 */
time_t t2 = 86400; /* One day later (86400 = 24 * 60 * 60) */
time_t t3 = 1747267200; /* Some time in May 2025 */
/* How many seconds between t1 and t2? */
long diff = (long)(t2 - t1);
printf("Difference: %ld seconds\n", diff); /* prints 86400 */
return 0;
}
On a 32-bit system, time_t is typically a 32-bit signed integer. On a 64-bit system, it is a 64-bit signed integer. This distinction is at the heart of the Year 2038 problem.
| Architecture | time_t size | Maximum representable date |
|---|---|---|
| 32-bit Linux | 4 bytes (signed) | 19 January 2038, 03:14:07 |
| 64-bit Linux | 8 bytes (signed) | 292 billion years from now |
A signed 32-bit integer can hold values from -2,147,483,648 to +2,147,483,647. When time_t is a 32-bit signed integer and its value reaches 2,147,483,647, adding just one more second causes an integer overflow — the value wraps around to -2,147,483,648, which corresponds to 13 December 1901.
Analogy: Imagine an old car odometer that only shows 5 digits. Once it hits 99,999 km, the next kilometre rolls it back to 00,000 km. Anyone reading it thinks the car has barely been driven. The same thing happens with a 32-bit time_t on 19 January 2038.
/* Demonstration of the 2038 overflow (illustrative only) */
#include <stdio.h>
#include <stdint.h>
int main(void)
{
int32_t t = 2147483647; /* Maximum 32-bit signed value (2038 limit) */
printf("Before overflow: %d\n", t);
t = t + 1; /* Adding 1 second wraps around */
printf("After +1 second: %d\n", t); /* prints -2147483648 ! */
return 0;
}
| System Type | Risk Level | Reason |
|---|---|---|
| 64-bit desktop/server Linux | Safe | time_t is 64-bit, won’t overflow until ~292 billion years |
| 32-bit embedded Linux (routers, industrial controllers) | At Risk | Long product lifespans, often not updated, 32-bit time_t |
| Legacy data & file formats with 32-bit timestamps | Medium Risk | Old binary formats storing int32_t timestamps; need migration |
Embedded systems engineers take note: a motor controller programmed today with a 32-bit time_t that calculates future maintenance schedules could produce wrong dates after 2038 if still running. This is a real concern in industrial and automotive sectors.
UNIX stores time internally in UTC — not in any local timezone. This is deliberate. Consider a server that moves from New York to Tokyo — its files and logs should not suddenly show wrong timestamps. UTC is a stable, timezone-independent reference. Conversion to local time happens only when displaying time to the user.
| Stored internally | Displayed to user |
|---|---|
| time_t = 1747267200 (UTC) | Converted to IST (+5:30), displayed as 15 May 2025, 05:30 AM |
Up Next in This Series
Part 3 covers the gettimeofday() and time() system calls — how to actually read the current calendar time from your C program.
