System and users
date
Print the current date and time in any format, or convert and calculate dates.
date [OPTION...] [+FORMAT]
date prints the current time, and with a +FORMAT argument it prints it any way you like:
%Y-%m-%d for a sortable date, %s for Unix seconds, %H%M%S for a filename. GNU date also
parses dates with -d: absolute ones (2026-03-14 08:00), Unix timestamps (@1700000000)
and relative phrases (yesterday, +3 days, next friday). Parsing plus formatting covers most
date arithmetic a shell script needs, with no extra tools.
Two settings decide what you see. TZ picks the time zone (TZ=Asia/Tokyo date), and -u
forces UTC. The examples run with TZ=UTC, so local time and UTC coincide here; on your machine
they will not. For logs and anything compared across machines, use UTC or include the offset.
The parsing options are where Linux and macOS differ most: macOS date has no -d, and -r
means something else there. The GNU/BSD notes below give the equivalents.
Examples
Print the current date and time
date
Sat Oct 31 20:19:35 UTC 2026
The default format is locale-dependent; in the C locale it is weekday, month, day, time, zone and year. Do not parse this output in scripts; ask for a format instead.
Print a date in a custom format
date '+%Y-%m-%d %H:%M:%S'
2026-10-31 20:19:35
+ introduces the format; %Y is the four-digit year, %m and %d zero-padded month and
day, %H:%M:%S the 24-hour time. Quote the format whenever it contains spaces.
Write the date out in words
date -d 2026-03-04 '+%A, %B %-d, %Y (day %j, week %V)'
Wednesday, March 4, 2026 (day 063, week 10)
%A and %B are the full weekday and month names, %-d drops the leading zero (a GNU
extension), %j is the day of the year and %V the ISO week number.
Print ISO 8601 and RFC timestamps
date -d '2026-03-14 08:00:01' -Iseconds
date -d '2026-03-14 08:00:01' --rfc-3339=seconds
date -d '2026-03-14 08:00:01' -R
2026-03-14T08:00:01+00:00 2026-03-14 08:00:01+00:00 Sat, 14 Mar 2026 08:00:01 +0000
-I (ISO 8601) puts a T between date and time and appends the UTC offset. RFC 3339 is the
same with a space, and -R is the email-header format (RFC 5322).
Put a timestamp in a file name
cp todo.txt "todo-$(date +%Y%m%d-%H%M%S).txt"
ls todo*
todo-20261031-201935.txt todo.txt
Year-first numeric stamps sort chronologically with a plain ls. Avoid : in file names;
it is awkward on Windows filesystems and in scp arguments.
Show the time in UTC or in another time zone
date -u -d '2026-07-01 12:00' '+UTC: %H:%M %Z'
TZ=America/New_York date -d '2026-07-01 12:00 UTC' '+New York: %H:%M %Z (%z)'
TZ=Asia/Kolkata date -d '2026-07-01 12:00 UTC' '+Kolkata: %H:%M %Z (%z)'
UTC: 12:00 UTC New York: 08:00 EDT (-0400) Kolkata: 17:30 IST (+0530)
-u formats in UTC; setting TZ for one command formats in that zone. The UTC inside the
-d string pins the input, so all three lines describe the same instant. In July New York is
on daylight time (EDT, -0400).
Get the current Unix timestamp
date +%s
1793477975
%s is seconds since 1970-01-01 00:00:00 UTC, the same in every time zone. It is the easiest
form to compare or subtract in a script.
Get a timestamp with milliseconds
date +%s%3N
1793477975709
%N is nanoseconds and %3N keeps the first three digits, giving milliseconds since the
epoch, the unit JavaScript and many APIs use.
Convert a Unix timestamp to a date
date -u -d @1700000000
date -u -d @1700000000 +%F
Tue Nov 14 22:13:20 UTC 2023 2023-11-14
An @ before a number means "seconds since the epoch". %F is shorthand for %Y-%m-%d.
Convert a date to a Unix timestamp
date -d '2026-03-14 08:00:01 UTC' +%s
1773475201
-d parses the string and +%s prints it as epoch seconds. Including UTC (or an offset
like +02:00) in the input avoids depending on the machine's time zone.
Calculate relative dates
date -d '2026-03-14 +3 days' +%F
date -d '2026-03-14 -2 weeks' +%F
date -d '2026-01-31 +1 month' +%F
date -d '2026-03-14 08:00 UTC +90 minutes' '+%F %H:%M'
2026-03-17 2026-02-28 2026-03-03 2026-03-14 09:30
The phrase after the date adjusts it. Note the third line: one month after January 31 is
"February 31", which GNU date normalizes to March 3. Count days instead when that matters.
Units go down to minutes and seconds, as the last line shows.
Get dates relative to today
echo "app-$(date -d yesterday +%F).log"
date -d 'next friday' '+next Friday is %F'
date -d '3 days ago' '+3 days ago was %A'
app-2026-10-30.log next Friday is 2026-11-06 3 days ago was Wednesday
yesterday, tomorrow, 3 days ago, next friday and last monday are understood
relative to the current time, which makes rotated-log names and report ranges one-liners.
Count the days between two dates
start=$(date -u -d 2026-03-14 +%s)
end=$(date -u -d 2026-12-25 +%s)
echo "$(( (end - start) / 86400 )) days"
286 days
Convert both dates to epoch seconds and divide the difference by 86400. Parsing both in UTC
(-u) avoids an off-by-one when a daylight-saving change falls between them.
Show a file's modification time
date -r todo.txt '+%F %T'
2026-10-24 21:28:49
With GNU date, -r FILE prints the file's last modification time instead of the current
time, in any format you choose. %T is shorthand for %H:%M:%S.
Validate a date string
date -d 2026-02-28 +%F
date -d 2026-02-30 +%F
2026-02-28 date: invalid date ‘2026-02-30’
An impossible date is rejected with invalid date and exit status 1, so `date -d "$input"
/dev/null 2>&1` works as a validity check for user input.
Common pitfalls
Formatting with
%Mwhen you mean month.%Mis minutes; month is%m. Likewise%Sis seconds and%sepoch seconds.Parsing user-supplied dates in the local zone.
date -d '2026-03-14 08:00'means 08:00 wherever the script runs; addUTCor an offset, or run with-u.Calling
dateseveral times in one script to build one timestamp. If the clock ticks over between calls the pieces disagree; capturenow=$(date +%s)once and format it withdate -d @$now.Combining a weekday phrase with an explicit date.
date -d '2026-03-14 next friday'silently prints March 14; weekday phrases only move relative to today. Use day arithmetic (+6 days) on fixed dates.Adding months to the 29th, 30th or 31st.
+1 monthoverflows into the following month instead of clamping to the last day.date -s(set the clock) needs root and is normally the job of NTP (timedatectl, chrony); changing the time by hand on a server can confuse logs and certificate checks.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
macOS/BSD
datehas no-d. Relative dates use-v:date -v-1dis yesterday,date -v+3mthree months ahead. Parsing uses-j -f INFORMAT STRING:date -j -f '%Y-%m-%d' 2026-03-14 +%s(-jmeans do not try to set the clock).-rmeans different things: on GNU it takes a file and prints its mtime; on macOS/BSDdate -r 1700000000converts epoch seconds (the GNU form isdate -d @1700000000). For a file's mtime on macOS usestat -f %m FILE.%N(nanoseconds) and the%-d-style padding flags are GNU; macOSdatedoes not support%N.--rfc-3339,-Rand the long options are GNU-only. Installing GNU coreutils on macOS (Homebrew) provides GNU date asgdate.
Options worth knowing
A selection, described in our own words. For the full list, see date(1) or date --help.
| Option | What it does |
|---|---|
-d, --date STRING | Display the time described by STRING instead of now. |
-u, --utc | Use UTC instead of the local time zone. |
-I, --iso-8601[=FMT] | Print ISO 8601; FMT is date (default), hours, minutes, seconds or ns. |
-R, --rfc-email | Print in the RFC 5322 email date format. |
--rfc-3339 FMT | Print RFC 3339 format; FMT is date, seconds or ns. |
-r, --reference FILE | Display FILE's last modification time. |
-f, --file DATEFILE | Parse and print each line of DATEFILE as a date. |
-s, --set STRING | Set the system clock to STRING (needs root). |
--debug | Explain how the date string was parsed, on stderr. |
--resolution | Print the clock's available resolution. |
Related
calPrint a calendar for a month, a few months, or a whole year.touchUpdate a file's timestamps, creating it empty if it does not exist.statShow a file's metadata (size, permissions, owner, inode, timestamps), or print chosen fields in your own format.sleepPause for a given amount of time, in seconds by default, with m, h and d suffixes and fractions allowed.uptimeShow how long the system has been running, how many users are logged in, and the load averages.- Command substitutionCapturing a command's output with $(...), what happens to trailing newlines and stderr, how to check the exit status, and the local trap that hides failures.
- ArithmeticInteger math with $(( )) and (( )), the exit status of (( )) that breaks set -e, leading-zero octal surprises, and what to use for decimals.