date - Today is tomorrow's yesterday.

mail

date

Usage :

Set, display and manipulate dates.

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
display time described by dateString, using keywords such as now, yesterday, today, tomorrow, day(s), week(s), month(s), year(s) :
  • date --date "now -60 days"
  • date --date=tomorrow
  • 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
-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) :

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
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

Examples of 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
2011-12-29_10-23-08 date +%F_%H-%M-%S (almost) same as above without the : characters, 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 current Unix timestamp
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 /...)

Example :

Convert dates :

Unix timestamp into date (source) :
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
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
UNIX time : 2000000000	==>	LOCAL TIME : Wed May 18 05:33:20 CEST 2033
Date string YYYY-MM-DD hh:mm:ss date into Unix timestamp :
date -d"2013-12-16 00:30:01" +%s
Unix timestamp into a formatted date string :
date -d@1387215550 "+%d/%m/%Y - %H:%M"

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