opscape

System and users

date

Print the current date and time in any format, or convert and calculate dates.

date [OPTION...] [+FORMAT]

15 of 15 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: date(1)

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
explain
output
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'
explain
output
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)'
explain
output
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
output
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*
output
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)'
output
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
explain
output
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
explain
output
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
output
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
explain
output
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'
output
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'
output
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"
output
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'
explain
output
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
outputexit 1
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 %M when you mean month. %M is minutes; month is %m. Likewise %S is seconds and %s epoch seconds.

  • Parsing user-supplied dates in the local zone. date -d '2026-03-14 08:00' means 08:00 wherever the script runs; add UTC or an offset, or run with -u.

  • Calling date several times in one script to build one timestamp. If the clock ticks over between calls the pieces disagree; capture now=$(date +%s) once and format it with date -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 month overflows 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 date has no -d. Relative dates use -v: date -v-1d is yesterday, date -v+3m three months ahead. Parsing uses -j -f INFORMAT STRING: date -j -f '%Y-%m-%d' 2026-03-14 +%s (-j means do not try to set the clock).

  • -r means different things: on GNU it takes a file and prints its mtime; on macOS/BSD date -r 1700000000 converts epoch seconds (the GNU form is date -d @1700000000). For a file's mtime on macOS use stat -f %m FILE.

  • %N (nanoseconds) and the %-d-style padding flags are GNU; macOS date does not support %N.

  • --rfc-3339, -R and the long options are GNU-only. Installing GNU coreutils on macOS (Homebrew) provides GNU date as gdate.

Options worth knowing

A selection, described in our own words. For the full list, see date(1) or date --help.

OptionWhat it does
-d, --date STRINGDisplay the time described by STRING instead of now.
-u, --utcUse 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-emailPrint in the RFC 5322 email date format.
--rfc-3339 FMTPrint RFC 3339 format; FMT is date, seconds or ns.
-r, --reference FILEDisplay FILE's last modification time.
-f, --file DATEFILEParse and print each line of DATEFILE as a date.
-s, --set STRINGSet the system clock to STRING (needs root).
--debugExplain how the date string was parsed, on stderr.
--resolutionPrint the clock's available resolution.

Related