Linux Epoch Time
Linux epoch time is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970, stored and displayed as a plain integer by every major Linux utility from the date command through the system clock API.

A single timestamp such as 1700000000 corresponds to 14 November 2023 at 22:13:20 UTC, and the same integer appears in file metadata, log lines, HTTP headers, and database columns across the entire server stack. Because the Linux Kernel exposes this counter through the gettimeofday and clock_gettime system calls, every layer above it, from the shell to the application server, inherits the same reference point without any additional configuration.
The day-to-day workflow for a sysadmin who works with logs, cron schedules, and monitoring graphs on a Linux server touches these utilities and references: Linux Commands for the shell one-liners that convert and filter, Find Files on Linux for locating logs older than a given timestamp, and Linux for the LAMP stack when a PHP or Apache access log needs its request time decoded back to a human date.
What the epoch number actually represents
Every epoch value you see on a Linux box is a count of seconds, not milliseconds or nanoseconds, unless the tool explicitly appends a fractional part. The reference instant, 1 January 1970 00:00:00 UTC, is hard-coded in the C library and in the Linux Kernel source under include/uapi/linux/time.h as the zero point of struct timeval. Positive values count forward from that instant; negative values count backward and appear only in date strings produced by the date command when you request a time before 1970. A file created today carries a modification timestamp of roughly 1725500000 seconds, and the gap between that number and 0 is exactly the age of the file in seconds.
Converting with the date command
To convert between a human-readable date and its epoch equivalent, the date command is the single tool you need. The table below lists the three conversions you will run most often on a running server.
| Goal | Command | Example output |
|---|---|---|
| Human date to epoch | date -d "2024-06-15 08:30:00 UTC" +%s | 1718442600 |
| Epoch to human date | date -d @1718442600 | Sat Jun 15 08:30:00 UTC 2024 |
| Now in epoch | date +%s | 1751798400 |
The -d flag accepts almost any date format the GNU date parser understands, so you can feed it an HTTP date like "Sat, 15 Jun 2024 08:30:00 GMT" and get the same epoch integer. The %s format specifier prints the seconds; %N appends nanoseconds for sub-second precision when a log line includes fractional timing. If your distribution ships the BusyBox date applet instead of the GNU version, the -d syntax changes to -d "seconds@1718442600", which is worth noting when you SSH into a minimal container.
Reading epoch values in log files
Epoch timestamps show up in Linux log files in three common formats: a bare integer at the start of each line, a comma-separated seconds.milliseconds pair, or an ISO 8601 string that you must convert before you can sort numerically. Apache access logs in the combined format write the request time as [15/Jun/2024:08:30:00 +0000], which awk converts with mktime after you split the fields. Nginx access logs use the same bracketed date by default, but you can switch to $msec in the log_format directive to emit a floating-point epoch such as 1718442600.123. Journal entries in /var/log/journal carry a 64-bit monotonic clock value plus a realtime wall clock in microseconds; the journalctl tool accepts --since @1718442600 to start reading from a specific epoch second.
When you grep a log for requests that arrived in a 5 minute window, you first convert the window boundaries to epoch with date -d, then filter with awk on the numeric field. This avoids the string-comparison trap where "Jun 15" sorts after "Dec 01" alphabetically and gives you a wrong time range.
Epoch precision and the limits of 32-bit time
Linux Commands that return epoch seconds as a 32-bit signed integer can represent values from roughly 13 December 1901 to 19 January 2038, a span of 136 years. The 32-bit limit, known as the Y2038 problem, affects legacy binaries compiled without 64-bit time support; the Linux Kernel has used 64-bit time_t since version 3.0, and every mainstream distribution ships 64-bit libc today, so new servers are unaffected. If you maintain a 32-bit embedded board that still calls a 32-bit clock() wrapper, the counter will wrap on 19 January 2038 at 03:14:07 UTC and every timestamp after that point will be negative. For most desktop and server workloads the practical precision question is not 32-bit versus 64-bit but whether the log line records seconds or milliseconds; a 1000 millisecond gap between two log lines is visible in a $msec field but invisible in a %s field.
Using epoch values in scripts and cron
Epoch arithmetic inside a shell script is a two-step operation: capture the current time with now=$(date +%s), then compare it against a stored value. A rotation script that deletes access logs older than 30 days stores the cutoff as $(( $(date +%s) - 2592000 )) and passes that to find with -newermt. The find command, which is the tool you reach for when you need to find files on Linux older than a date threshold, accepts -mtime 30 directly, but the epoch form gives you sub-day granularity when the retention window is 6 hours or 90 minutes instead of a whole number of days.
Cron expressions work in wall-clock time, not epoch, so the conversion only matters when a monitoring script compares the job start time against an SLA threshold. A typical check reads the last successful run from a state file, converts both the file timestamp and the current time to epoch, and alerts if the gap exceeds 3600 seconds. Writing that comparison in epoch seconds avoids timezone pitfalls entirely because the epoch is always UTC regardless of the server's /etc/localtime setting.
Epoch time across the web stack
When a request flows through a LAMP or equivalent stack on a Linux server, the same epoch instant appears in at least 4 places: the Apache or Nginx access log, the PHP error_log entry, the database row insert time stored as a UNIX_TIMESTAMP, and the HTTP Last-Modified header converted back to a GMT date. The Last-Modified header is the one place the raw integer does not travel on the wire; the RFC 7231 mandates an HTTP-date format like Sat, 01 Jan 2004 00:59:59 GMT, and the web server performs the conversion internally. For cache validation, a 1 second difference between the epoch in your database and the epoch the browser computes from the Last-Modified header can flip a conditional request from a 200 OK to a 304 Not Modified, so keeping the application timezone set to UTC (the default for PHP with date.timezone = UTC) eliminates a whole class of off-by-one-day bugs in reports that filter on timestamp ranges.
The epoch integer is the one time format that every component in the stack already speaks. You do not configure a timezone for it, you do not parse a locale, and you do not handle a leap second, because the counter simply increments by 1 each second. For a sysadmin whose daily work is reading logs, writing rotation scripts, and debugging a request that timed out 47 seconds after it started, treating the epoch as the native unit of time and converting to a human date only at the point of display removes the most common source of timezone-related errors on a Linux server.