Time in a computer system is more than one number. A filesystem uses several timestamps to record access, content modification, and metadata changes, while applications must also handle UTC, time-zone rules, and historical dates. This article first explains Linux file times, stat, touch, and atime mount options, then covers Unix timestamps and IANA time zones.

1. File timestamps, system commands, and mount options

1.1 Identify four timestamps with stat

The stat command displays a file’s timestamps and inode metadata:

$ stat /var/log/syslog
  File: /var/log/syslog
  Size: 1048576         Blocks: 2048       IO Block: 4096   regular file
Device: 253,0           Inode: 131074      Links: 1
Access: (0640/-rw-r-----)  Uid: (    0/    root)   Gid: (    4/     adm)
Access: 2026-07-31 21:30:00.123456789 +0800
Modify: 2026-07-31 20:15:33.987654321 +0800
Change: 2026-07-31 20:15:33.987654321 +0800
 Birth: 2026-07-01 08:00:00.000000000 +0800
FieldTimestampFull nameMeaningOperations that commonly update it
Access:atimeAccess TimeMost recent access timecat, less, grep, read()
Modify:mtimeModification TimeMost recent content modificationwrite(), truncate(), saving in an editor
Change:ctimeChange TimeMost recent inode-status changechmod, chown, link-count changes, content modification
Birth:birthtimeBirth/Creation TimeTime when the file was createdRecorded at creation when the filesystem supports it

The c in ctime means change, not creation. Modifying content changes both mtime and ctime; changing permissions, ownership, or link count normally changes only ctime. Linux birthtime support depends on the kernel, filesystem, and user-space tools, so stat may display -. Ordinary file APIs generally cannot set birthtime as they can mtime, and copying data into a new file gives the copy a new creation time.

An mtime is not a trustworthy audit record either. touch -m file can change it, while rsync —archive can preserve the source file’s mtime. Security auditing requires an audit log or another record that ordinary file operations cannot easily rewrite.

GNU stat has format options that are useful in scripts:

stat -c '%Y' filename
stat -c '%W' filename
stat -c '%x %y %z %w' filename
stat -c 'mtime=%Y atime=%X ctime=%Z' /etc/passwd

%Y, %X, and %Z output mtime, atime, and ctime as Unix seconds. %W outputs birthtime in seconds and commonly returns 0 when birthtime is unavailable. The BSD stat on macOS uses -f and different format specifiers, so a portable script must handle the two implementations separately.

1.2 What atime can and cannot tell you

An atime can provide an approximate indication of when a file was last read. Some mail clients compare atime with mtime to decide whether mail has been read, temporary-file cleaners may retain active files according to access time, and cache systems may consult access time when choosing entries to evict.

Atime stores only the latest access time. It does not record who read the file, how often it was read, or its access history, and relatime and noatime reduce its precision further. Atime therefore cannot provide security forensics or compliance auditing by itself. Use Linux Audit, application logs, or the storage system’s audit facility when access records must be reliable.

1.3 strictatime, relatime, and noatime

Updating atime turns a read into an inode metadata write. Scanning logs, static assets, or large collections of small files can therefore increase write amplification. Linux offers three common mount policies:

ModeUpdate ruleUse and cost
strictatimeUpdate atime according to strict access-time semanticsMost precise, but read-heavy workloads cause more metadata writes
relatimeUpdate when atime is older than mtime or ctime, or sufficiently oldPreserves most compatibility needs while greatly reducing writes; common Linux default
noatimeDo not update atime on readsSuitable for read-heavy filesystems whose software does not depend on atime

Run findmnt -no OPTIONS /mountpoint or inspect /proc/mounts to determine the active option. Before selecting noatime, check whether mail, temporary-file cleanup, or backup software relies on access times. Use strictatime only when an application has a concrete requirement for precise atime behavior.

1.4 How file operations affect timestamps

The following table shows typical effects. Whether an atime reaches disk still depends on mount options, and an editor may save by writing a temporary file and renaming it, so the table describes common behavior rather than an absolute guarantee across every filesystem and tool.

OperationatimemtimectimeExplanation
echo “data” >> fileUsually unchangedUpdatedUpdatedAppends in write-only mode without reading existing content
echo “data” > fileUsually unchangedUpdatedUpdatedTruncates and writes the same file
cat fileUpdated according to mount policyUnchangedUnchangedReads file content
touch fileUpdatedUpdatedUpdatedSets atime and mtime, which also changes ctime
touch -m fileUnchangedUpdatedUpdatedExplicitly sets mtime
chmod fileUnchangedUnchangedUpdatedChanges inode metadata
sed -i ‘s/a/b/’ fileImplementation-dependentUpdatedUpdatedCommon implementations read the old file and replace it

A write-only append does not update atime merely because strictatime is active; accessing file content triggers atime handling. The final timestamps may still differ if a script reads before writing, another process reads concurrently, or a tool uses a different save procedure. A program that must preserve an earlier atime can record the timestamp and restore it with touch -a -d after writing. Lower-level programs can use O_NOATIME, subject to permission checks, to prevent their own reads from changing atime.

This experiment shows the typical result of a write-only append:

$ stat -c 'atime=%x mtime=%y ctime=%z' test.txt
atime=2026-07-31 20:00:00 mtime=2026-07-31 20:00:00 ctime=2026-07-31 20:00:00

$ echo "new line" >> test.txt
$ stat -c 'atime=%x mtime=%y ctime=%z' test.txt
atime=2026-07-31 20:00:00 mtime=2026-07-31 21:45:00 ctime=2026-07-31 21:45:00

1.5 date and the Linux time-tool ecosystem

GNU date can display, parse, and convert times:

date '+%Y-%m-%dT%H:%M:%S%z'
date -u '+%Y-%m-%dT%H:%M:%SZ'
date '+%s'

date -d @1785498540 '+%Y-%m-%d %H:%M:%S %z'
date -d '2026-07-31 21:39:00' '+%s'

TZ='America/Los_Angeles' date -d '2026-07-31 21:39:00 UTC' '+%Y-%m-%d %H:%M:%S %Z'
date -d 'now + 3 days - 2 hours' '+%Y-%m-%d %H:%M:%S'
date -d 'next monday 09:00' '+%s'

The date -d option is a GNU extension and is not part of POSIX. BusyBox and macOS provide different date syntax, so scripts cannot assume that every platform accepts the same options.

Tool or libraryPurposeNotes
dateQuery and convert time in a shellGNU, BusyBox, and BSD variants differ
timedatectlManage system time zone, NTP, and RTCProvided by systemd
hwclockRead and write the hardware clockDistinguish UTC and local-time modes
chronyc, ntpqInspect time synchronizationReport sources, offset, and drift
tzselectChoose an IANA time zoneHelps identify a value for TZ
zdumpDisplay time-zone transition rulesUseful for diagnosing tzdata problems
C time.hApplication-level time APIIncludes interfaces such as gmtime_r and strftime

1.6 Change file times with touch

The touch command can set atime and mtime. The kernel updates ctime when the inode state changes:

touch -m -t 202301011200.00 filename
touch -a -t 202301011200.00 filename
touch -t 202301011200.00 filename
touch -r reference_file target_file

The first command specifies only mtime, the second only atime, the third both, and the fourth copies the reference file’s atime and mtime to the target. touch cannot directly set ctime or birthtime. Do not alter inode timestamps with debugfs on a production filesystem.

2. Unix time and time-zone conversion

2.1 A Unix timestamp is a signed time axis

A Unix timestamp uses 1970-01-01T00:00:00Z as zero. Negative values represent earlier instants, so the epoch is not the beginning of representable time.

UTC instantUnix timestamp (seconds)Meaning
2026-07-31T13:39:00Z1785498540After the epoch
1970-01-01T00:00:00Z0The epoch
1949-10-01T00:00:00Z-636249600Before the epoch
1900-01-01T00:00:00Z-2208988800Before the epoch

Check the data type and database range before storing historical times. An unsigned integer cannot represent negative values, and signed 32-bit Unix seconds overflow in 2038, so systems commonly use a 64-bit type with a documented range. The range of MySQL TIMESTAMP depends on version and implementation; historical data may call for DATETIME or an integer timestamp according to its business meaning.

For early historical dates, the IANA database may have only approximate local rules and may return Local Mean Time (LMT). Front-end controls, serialization libraries, and monitoring tools may also mishandle negative timestamps. Test the storage, API, and display path separately when dates before 1970 matter.

2.2 Fixed offsets, abbreviations, and IANA zones

Military or NATO letter zones map letters to fixed UTC offsets. Z means UTC, while J means the observer’s local time. Except for Z as adopted by ISO 8601, these communication shortcuts contain neither daylight-saving transitions nor political rules and should not identify a user’s time zone in software.

Human-readable abbreviations such as PDT, CST, and IST are ambiguous too. CST can mean China Standard Time or Central Standard Time; IST can refer to India, Ireland, or Israel. An abbreviation is suitable only for display in an unambiguous context, not as a durable zone identifier.

Applications should use IANA names in Area/Location form, such as Asia/Shanghai, America/Los_Angeles, and Asia/Pyongyang. IANA tzdata records historical offsets, daylight-saving transitions, and rule changes for a region. A fixed +08:00 describes only an offset at an instant and cannot represent a complete time zone.

The NATO fixed-offset letters are listed below; J has no fixed offset:

LetterUTC offsetLetterUTC offset
A / Alpha+01:00N / November-01:00
B / Bravo+02:00O / Oscar-02:00
C / Charlie+03:00P / Papa-03:00
D / Delta+04:00Q / Quebec-04:00
E / Echo+05:00R / Romeo-05:00
F / Foxtrot+06:00S / Sierra-06:00
G / Golf+07:00T / Tango-07:00
H / Hotel+08:00U / Uniform-08:00
I / India+09:00V / Victor-09:00
K / Kilo+10:00W / Whiskey-10:00
L / Lima+11:00X / X-ray-11:00
M / Mike+12:00Y / Yankee-12:00
Z / Zulu±00:00J / JulietLocal time

2.3 Time-zone rules change

North Korea changed from UTC+09:00 to UTC+08:30 on August 15, 2015, and returned to UTC+09:00 on May 5, 2018. Hard-coding the country’s zone as +08:30 makes local times after the 2018 change wrong. With Asia/Pyongyang and current tzdata, a standard library can apply the rule for the date being converted.

Daylight-saving changes, administrative boundaries, and temporary government decisions create the same problem elsewhere. Business data often needs to preserve both “the instant when an event occurred” and “the time zone selected by the user.” UTC can represent the former, while an IANA name preserves the rules needed for local display and calendar arithmetic.

2.4 Storage, transport, and display principles

A system can represent internal instants with signed 64-bit UTC timestamps or datetime types that have explicit UTC semantics. An API should emit ISO 8601, such as 2026-07-31T13:39:00Z or the offset-bearing 2026-07-31T21:39:00+08:00. If a database must reconstruct a user’s future local schedule, it should also retain the IANA zone instead of storing only the current offset.

The display layer converts an instant according to user preference. Keep tzdata current, and add regression tests for daylight-saving gaps, repeated local times, negative historical timestamps, and the 2038 boundary. UTC timestamps identify instants well, but a calendar rule such as “09:00 on the last day of every month” cannot be represented by a fixed interval in seconds.

ScenarioError-prone choiceRecommended choice
Store a time zonePDT or integer +8An IANA name such as America/Los_Angeles
Represent UTC2026-07-31 13:39:002026-07-31T13:39:00Z
Represent a pre-1970 instantUINT32A signed 64-bit type with a documented range
Represent US Pacific local timePermanently hard-code UTC-7Use America/Los_Angeles
Inspect file timesRun only ls -lRun stat filename
Mount a read-heavy filesystemSelect strictatime by habitEvaluate relatime or noatime
Convert times in a shellAdd offsets by handUse TZ and a time-zone database

A timestamp maps an instant onto a numerical axis, while time-zone rules map an instant onto a local calendar. For both filesystem and application time, define the intended meaning before choosing a data type, command, or zone rule.