date - Today is tomorrow's yesterday.

mail

date

Usage

Flags

Flag Usage
(none)
  • display the current date and time : Wed Aug 5 09:35:06 CEST 2015
  • you can specify the output format
-d dateString
--date dateString
instruct date to work with dateString rather than with the current date+time. This is used mostly to
  • compute dates+times
  • extract date+time fields : month number, hour, number of seconds,
dateString :
  • can be the result of a previous date invocation
    date
    	jeu. 10 oct. 2024 09:00:37 CEST
    date -d $(date +%F) +%Y
    	2024
    date -d $(date +%F) +%S					⇐ all OK
    	00
    date -d $(date +%F) +%a
    	jeu.
    
    
    date -d $(date) +%Y
    	date: extra operand ‘oct.’
    	Try 'date --help' for more information.						⇐ KO
    date -d "$(date)" +%Y
    	date: invalid date ‘jeu. 10 oct. 2024 09:04:25 CEST’
    
    
    rightNow=$(date +%F); seconds=$(date -d "$rightNow" +%S); echo "right now : '$rightNow', seconds : '$seconds'"
    	right now : '2024-10-10', seconds : '00'					⇐ always '00' if seconds are missing in the input
    
    rightNow=$(date '+%F %H:%M:%S'); seconds=$(date -d "$rightNow" +%S); echo "right now : '$rightNow', seconds : '$seconds'"
    	right now : '2024-10-10 10:02:19', seconds : '19'						⇐ OK
    
    
  • can use keywords such as now, yesterday, today, tomorrow, day(s), week(s), month(s), year(s), :
    • date --date "-60 days"
      • unsigned integers are interpreted as +n
      • if the start date is omitted, +n / -n are relative to now : date --date 'now -60 days'; date --date '-60 days'
      • it is possible to combine different units : date --date='now'; date --date='-23hour'; date --date='-1day +1hour'
    • date --date=tomorrow
    • date -d "2023-01-29 +42days"
    • for unitOfTime in day week month year; do for number in {1..3}; do echo -en "+$number$unitOfTime :\t"; date --date "now +$number$unitOfTime"; done; done
more about date strings
--iso-8601
--iso-8601=precision
display date/time using the ISO 8601 format :
date; for precision in date hours minutes seconds ns; do echo -n "$precision : "; date --iso-8601="$precision"; done
Fri 11 Mar 2022 09:10:22 AM CET				just date, for comparison
date :		2022-03-11				default precision
hours :	2022-03-11T09+01:00			up to the current hour
minutes :	2022-03-11T09:10+01:00			up to the current hour:minute
seconds :	2022-03-11T09:10:22+01:00		up to the current hour:minute:second
ns :		2022-03-11T09:10:22,111460006+01:00	up to the current hour:minute:second,nanosecond
-r file
--reference file
display the last modification time of file
-s dateString
--set dateString
set time described by dateString :
date --set="Oct 31 10:52:40"

Date strings (source) :

For full details :
  1. run info '(coreutils) date invocation'
  2. then select Date input formats | Relative items in date strings

The --date='dateString' is a human-readable format such as next Thursday or 1 month ago. A date string may contain items indicating :

  • calendar date
  • time of day
  • time zone
  • day of the week
  • relative time
  • relative date
  • numbers

Keywords

  • now is a synonym of today. Check it : date --date now; date --date today
  • tomorrow is today + 24 hours. The same goes on with yesterday and today. Check it : date --date yesterday; date --date today; date --date tomorrow

Examples

The commands below were run on the Friday 19th of July.
the basics
date
Fri 19 Jul 2019 11:17:29 AM CEST
date --date="today"			same as above
Fri 19 Jul 2019 11:17:44 AM CEST
date --date="tomorrow"
Sat 20 Jul 2019 11:17:54 AM CEST
date --date="next monday"
Mon 22 Jul 2019 12:00:00 AM CEST
date; TZ=GMT date			display current date+time in a different time zone
Tue Feb 20 09:32:07 AM CET 2024
Tue Feb 20 08:32:07 AM GMT 2024
dates in the future / in the past
date --date="3 days"
Mon 22 Jul 2019 11:22:13 AM CEST
date --date="3 days ago"		ago ...
Tue 16 Jul 2019 11:22:19 AM CEST
date --date="-3 days"			and negative values compute dates in the past ...
Tue 16 Jul 2019 11:22:25 AM CEST
date --date="-3 days ago"		unless you combine both 
Mon 22 Jul 2019 11:37:53 AM CEST
date --date="-1 year month"
Sun 19 Aug 2018 12:32:02 PM CEST	+1 is implied for units without a number
(void) / this / next
date --date="thursday"
Thu 25 Jul 2019 12:00:00 AM CEST
date --date="this thursday"
Thu 25 Jul 2019 12:00:00 AM CEST
date --date="next thursday"
Thu 25 Jul 2019 12:00:00 AM CEST

date --date="friday"
Fri 19 Jul 2019 12:00:00 AM CEST
date --date="this friday"
Fri 19 Jul 2019 12:00:00 AM CEST
date --date="next friday"
Fri 26 Jul 2019 12:00:00 AM CEST

date --date="saturday"
Sat 20 Jul 2019 12:00:00 AM CEST
date --date="this saturday"
Sat 20 Jul 2019 12:00:00 AM CEST
date --date="next saturday"
Sat 20 Jul 2019 12:00:00 AM CEST
  • (void) implies this
  • this weekDay means :
    • if today is a weekDay : the current day
    • otherwise : next weekDay
future weekdays :
date --date="next monday"
Mon 22 Jul 2019 12:00:00 AM CEST
date --date="1 monday"			same as next
Mon 22 Jul 2019 12:00:00 AM CEST
date --date="2 monday"
Mon 29 Jul 2019 12:00:00 AM CEST
date --date="second monday"		second is "1 second", not "the second from now"
Mon 22 Jul 2019 12:00:01 AM CEST
date --date="third monday"
Mon 05 Aug 2019 12:00:00 AM CEST
date --date="fourth monday"
Mon 12 Aug 2019 12:00:00 AM CEST
date --date="tenth monday"
Mon 23 Sep 2019 12:00:00 AM CEST
a specific timestamp in order to compute accurate start + end timestamps
  • You may run :
    outputFormat='+%F %H:%M:%S'; startTime=$(date "$outputFormat"); endTime=$(date -d '+2years' "$outputFormat"); echo -e "start :\t$startTime\nend :\t$endTime"
    which outputs values that are split by 2 full years (same second ) and is fine 99.99999999% of the time :
    start : 2024-12-05 15:37:40
    end :   2026-12-05 15:37:40
  • But if you run :
    outputFormat='+%F %H:%M:%S.%N'; startTime=$(date "$outputFormat"); endTime=$(date -d '+2years' "$outputFormat"); echo -e "start :\t$startTime\nend :\t$endTime"
    you get :
    start : 2024-12-05 15:50:47.065296725
    end :   2026-12-05 15:50:47.067093474
    which is milliseconds away from the exact "start +2years". This is because :
    • startTime is "now"
    • endTime is based on "now" + a delay, but this "now" occurred a blink after the "now" of startTime, hence the difference.
    I've never encountered a situation where it mattered, but for the sake of completeness, let's say it does, and continue
  • Now let's run :
    outputFormat='+%F %H:%M:%S.%N %Z'; currentDateTime=$(date "$outputFormat"); startTime=$(date -d "$currentDateTime" "$outputFormat"); endTime=$(date -d "$currentDateTime +2years" "$outputFormat"); echo -e "start :\t$startTime\nend :\t$endTime"
    start : 2024-12-05 16:07:50.159780462 CET
    end :   2026-12-05 16:07:50.159780462 CET
    For an unknown reason, if $currentDateTime has no timezone field (%Z), the computed value for $endTime is effectively after $startTime, but not by the specified delay.

Output format :

Output Format string Usage
20170201 date +%Y%m%d compact representation of a date that can be used in a filename
20181116_152852 date +%Y%m%d_%H%M%S
2018-11-29 15:51:36 date '+%F %H:%M:%S' Quotes are necessary when the format string has a space, otherwise you'll get a date: extra operand '%H:%M:%S' error message.
%F is a synonymous of %Y-%m-%d
2024-04-25
2011-12-29_10-23-08 date +%F_%H-%M-%S (almost) same as above except the : changed to _, which is better if this timestamp is part of a filename
1014 date +%H%M at time format
jeu., 28 nov. 2013 15:10:46 GMT date +"%a, %d %b %Y %H:%M:%S GMT" If-Modified-Since HTTP header date format
1387202860 date +%s Unix timestamp, see examples
Wed Mar 15
Fri Sep 1
date +"%a %b %-d" git log date format
the extra - prevents padding the day number with a leading 0 if <10.
this format ignores the year, which may have unexpected results if the Git history has commits on the "same day" of distinct years (which happened to me with Wed Dec 12 of 2018 and 2012)
Fri Mar 13 17:35:03 2020 +0100
date +"%a %b %-d %H:%M:%S %Y %z" git log long date format (depending on personal settings / aliases /...)
CEST +0200
date +"%Z %z" current timezone : alphabetic abbreviation, then numeric
16:22:22.056139331
date '+%H:%M:%S.%N' display nanoseconds

Example

Convert dates :

Date string YYYY-MM-DD hh:mm:ss to Unix timestamp :
date -d '2013-10-24 14:35:55' +%s
1382618155
Unix timestamp to date :
  • date -d @1387215550 '+%d/%m/%Y - %H:%M'
    16/12/2013 - 18:39
  • for unixTime in 1234567890 1500000000 1600000000 2000000000; do echo -e "UNIX time : $unixTime\t==>\tLOCAL TIME : $(date -d @$unixTime)"; done
    UNIX time : 1234567890	==>	LOCAL TIME : Sat Feb 14 00:31:30 CET 2009		Central European Time
    UNIX time : 1500000000	==>	LOCAL TIME : Fri Jul 14 04:40:00 CEST 2017
    UNIX time : 1600000000	==>	LOCAL TIME : Sun Sep 13 14:26:40 CEST 2020		Central European Summer Time, nothing's wrong with date 
    UNIX time : 2000000000	==>	LOCAL TIME : Wed May 18 05:33:20 CEST 2033

Compute the end of Epoch (source) :

date -d @$(echo $((2 ** 31 - 1)))

Compute the number of days since any past date :

echo "scale=3; ("$(date -d"now" +%s) - $(date -d"2016-12-18 10:05:00" +%s)") / 86400" | bc

Compute the number of days between 2 dates :

general case :
startDate='2016-12-18 10:05:00'; endDate='today'; echo "scale=1; ("$(date --date "$endDate" +%s) - $(date --date "$startDate" +%s)") / 86400" | bc
excluding start and end days :
  • startDate='yesterday'; endDate='tomorrow'; echo "scale=1; ("$(date --date "$endDate 00:00:00" +%s) - $(date --date "$startDate 23:59:59" +%s)") / 86400" | bc
  • startDate='20170330'; endDate='20170401'; printf %0.f $(echo "scale=1; ("$(date --date "$endDate" +%s) - $(date --date "$startDate" +%s)") / 86400 -1" | bc)
go even further :
startDate='2019-07-06'; endDate='2019-09-02'; nbDays=$(echo "scale=1; ("$(date --date "$endDate" +%s) - $(date --date "$startDate" +%s)") / 86400" | bc); halfNbDays=$(echo "scale=1; $nbDays/2" | bc); middleDay=$(date +"%F (%a)" --date "$startDate +$(echo $halfNbDays | cut -d'.' -f1) days"); echo -e "Nb days =|$nbDays\nHalf =|$halfNbDays\nMiddle day =|$middleDay" | column -s '|' -t
There's a hack to compute dates with integers only, which makes the whole command not exact if there's an odd number of days .

Compute an end date while still considering workdays and week-ends :

This is typically the kind of questions we face once having determined a list of tasks and their durations, and now having to plan all these.
  • I am convinced it would be possible to do this with date + Bash (believe me, I like scripting ! ), but in the light of getting-results-fast, LibreOffice Calc's workday function wins !
  • For those wondering, Excel has a similar workday function.

Travel back in time (and in logfiles) :

startYear='2014'
startMonth='08'
startDay='06'

startHour='13'
startMinute='00'
startSecond='00'

nbDaysBack=4
resolutionInHours=1	# number of hours between 2 generated datetimes

#dateTimeFormat='%d%m%y-%H'	# ddmmyy-hh
dateTimeFormat='%Y-%m-%d %H'	# yyyy-mm-dd hh

initialTimestamp=$(date -d"$startYear-$startMonth-$startDay $startHour:$startMinute:$startSecond" +%s)
nbLoops=$((24/$resolutionInHours*$nbDaysBack))
timestamp=$initialTimestamp
for i in $(seq 1 $nbLoops);do
	formattedDate=$(date -d@$timestamp +"$dateTimeFormat")
	echo $formattedDate

	# ... now do something smart with the formatted date !

	timestamp=$((timestamp-(3600*$resolutionInHours)))
done