linux date命令详解
2011-03-05 10:39:20 阿炯

使用方式 :
date [-u] [-d datestr] [-s datestr] [--utc] [--universal] [--date=datestr] [--set=datestr] [--help] [--version] [+FORMAT] [MMDDhhmm[[CC]YY][.ss]]

说明 :
date 可以用来显示或设定系统的日期与时间,在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记,其中可用的标记列表如下 :

时间方面 :
% : 印出 %
%n : 下一行
%t : 跳格
%H : 小时(00..23)
%I : 小时(01..12)
%k : 小时(0..23)
%l : 小时(1..12)
%M : 分钟(00..59)
%p : 显示本地 AM 或 PM
%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)
%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数
%S : 秒(00..61)
%T : 直接显示时间 (24 小时制)
%X : 相当于 %H:%M:%S
%Z : 显示时区

日期方面 :
%a : 星期几 (Sun..Sat)
%A : 星期几 (Sunday..Saturday)
%b : 月份 (Jan..Dec)
%B : 月份 (January..December)
%c : 直接显示日期与时间
%d : 日 (01..31)
%D : 直接显示日期 (mm/dd/yy)
%h : 同 %b
%j : 一年中的第几天 (001..366)
%m : 月份 (01..12)
%U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形)
%w : 一周中的第几天 (0..6)
%W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形)
%x : 直接显示日期 (mm/dd/yy)
%y : 年份的最后两位数字 (00.99)
%Y : 完整年份 (0000..9999)

若是不以加号作为开头,则表示要设定时间,而时间格式为 MMDDhhmm[[CC]YY][.ss],其中 MM 为月份,DD 为日,hh 为小时,mm 为分钟,CC 为年份前两位数字,YY 为年份后两位数字,ss 为秒数

参数 :
-d datestr : 显示 datestr 中所设定的时间 (非系统时间)
--help : 显示辅助信息
-s datestr : 将系统时间设为 datestr 中所设定的时间
-u : 显示目前的格林威治时间
--version : 显示版本编号

例子 :
显示时间后跳行,再显示目前日期 :
date '+%T%n%D'

显示月份与日数 :
date '+%B %d'

显示日期与设定时间(12:34:56) :
date --date '12:34:56'

用指定的格式显示时间。
$ date ‘+This date now is =>%x ,time is now =>%X '
This date now is =>11/12/10 ,time is now =>17:53:01

用预定的格式显示当前的时间。
# date
Fri Nov 26 15:20:18 CST 1999

设置时间为下午14点36分。
# date -s 14:36:00
Fri Nov 26 14:15:00 CST 2010

设置时间为1999年11月28号。
# date -s 991128
Sun Nov 28 00:00:00 CST 1999

设置一天前
# date --date "1 days ago" +"%Y-%m-%d"

由于Linux对man date -d 参数说的比较模糊,故举例如下:
# -d, --date=STRING  display time described by STRING, not 'now'

# date -d next-day +%Y%m%d #明天日期
20100328
# date -d last-day +%Y%m%d #昨天日期
20100326
# date -d yesterday +%Y%m%d #昨天日期
20100326
# date -d tomorrow +%Y%m%d #明天日期
20100328
# date -d last-month +%Y%m #上个月日期
201002
# date -d next-month +%Y%m #下个月日期
201004
# date -d next-year +%Y #明年日期
2010

DATE=$(date +%Y%m%d -d '2 days ago') #获得2天前的日期
20111022

DATE=$(date +%Y%m%d -d '2 day') #获得2天后的日期
20111026


时间设定
date -s //设置当前时间,只有root权限才能设置,其他只能查看。
date -s 20100523 //设置成20100523,这样会把具体时间设置成空00:00:00
date -s 01:01:01 //设置具体时间,不会对日期做更改
date -s “01:01:01 2010-05-23″ //这样可以设置全部时间
date -s “01:01:01 20100523″ //这样可以设置全部时间
date -s “2010-05-23 01:01:01″ //这样可以设置全部时间
date -s “20100523 01:01:01″ //这样可以设置全部时间

日期的运算
date +%Y%m%d       //显示前天年月日
date +%Y%m%d --date="+1 day"   //显示前一天的日期
date +%Y%m%d --date="-1 day"   //显示后一天的日期
date +%Y%m%d --date="-1 month"   //显示上一月的日期
date +%Y%m%d --date="+1 month"   //显示下一月的日期
date +%Y%m%d --date="-1 year"   //显示前一年的日期
date +%Y%m%d --date="+1 year"   //显示下一年的日期

注意 :
当不希望出现无意义的 0 时(比如说 1999/03/07),则可以在标记中插入 - 符号,比如说 date '+%-H:%-M:%-S' 会把时分秒中无意义的 0 给去掉,像是原本的 08:09:04 会变为 8:9:4。当以 root 身分更改了系统时间之后,可将系统时间与硬件时间同步(hwclock --set --date="03/05/10 08:57:48"),请记得以 hwclock -w 来将系统时间写入 CMOS 中,这样下次重新开机时系统时间才会持续抱持最新的正确值。

Date的格式化字符串总结如下:
u显示格林尼洛时间(UTC) 
MMDDhhmm[[CC]YY][.ss]设定时间,需要管理员权限。date 12292359
MM月份
DD天数
hh小时
mm分钟
CC年份前两位
YY年份后两位
ss秒钟
秒钟、年份为可选date 122923592006.59
+[%X]设定显示格式,默认输出格式:date +%Y年%m月%d日%A%H:%M:%S%Z
格式控制%n换行
%t制表符
小时%H00~23
%I01~12
%k0~23
%l1~12
%pAM|PM
分、秒%M分钟(00~59)
%S秒(00..61)
%Thh:mm:ss
%rhh:mm:ss AM|PM
%s从 1970年1月1日00:00:00 UTC 到目前为止的秒数
%X%H:%M:%S
%Z时区
星期%aSun~Sat
%ASunday~Saturday
%w一周中的第几天(0~6)
年份%Y0000~9999
%y00~99
月份%m01~12
%bJan~Dec
%h
%BJanuary~December
日期%c完整日期时间
%d01~31
%j001~366
%x本地格式日期
%Dmm/dd/yy
一年中的第几周%U以 Sunday 为一周的第一天
%W以 Monday 为一周的第一天


-------------------------------------------------------------------
扩展功能

date 工具能够告终更多的工作,不但仅只是打印出目前的系统日期。能够利用它来获得给定的日期究竟是礼拜几,并获得相对于目前日期的相对日期。如某一天是礼拜几。
GNU 对 date 号召的另一个伸展是 -d 选项,当您的桌上未曾日历表时(UNIX 用户无须要日历表),该选项极其有用。利用这秉功能壮大的选项,穿越将日期作为引号括起来的参数供给,能够迅速地查明一个特定的日期究竟是礼拜几:
$ date -d "nov 22"
Wed Nov 22 00:00:00 EST 2006

在本示例中能够看到今年的 11 月 22 日是礼拜三。因而假想在 11 月 22 日举行一个重大的会议,能够即刻打听到这一天是礼拜三,而这一天将赶到驻地办公室。

获得相对日期
d 选项还能够告诉您,相对于目前日期若干天的究竟是哪一天,从目前开始的若干天或若干礼拜尔后,可能过去(过去)。穿越将这个相对偏移利用引号括起来,作为 -d 选项的参数,就能够告终这项任务。例如必需打听两礼拜后的日期:
$ date -d '2 weeks'
关于利用该指令,还有其他一些重要的措施。利用 next/last 指示字能够获得尔后的礼拜几是哪一天:
$ date -d 'next monday' (下周一的日期)
$ date -d next-day +%Y%m%d(明天的日期)可能:date -d tomorrow +%Y%m%d
$ date -d last-day +%Y%m%d(昨天的日期) 可能:date -d yesterday +%Y%m%d
$ date -d last-month +%Y%m(上个月是几月)
$ date -d next-month +%Y%m(下个月是几月)

利用 ago 指示字能够获得过去的日期:
$ date -d '30 days ago' (30天前的日期)

能够利用负数以获得相反的日期:
$ date -d 'dec 14 -2 weeks' (相对:dec 14这个日期的两周前的日期)
$ date -d '-100 days' (100天过去的日期)
$ date -d '50 days'(50天后的日期)

date -d '1 second ago' && date

date +"%Y-%m-%dT%H:%M:%S"    (ISO8601时间格式)

date -d "+10 days"

echo $(date -d "-3 second")
date --date="+1 seconds" '+%Y-%m-%d %T'

date && daste -s date +%Y-%m-%dT%H:%M:%S --date="+1 second"
date && date -s date --date="+1 seconds" '+%Y-%m-%d %T' && date # 将会报错
date: 显示与设置时间的选项不能同时使用

$ date +%x.%H:%M:%S:%N
2023年09月08日.12:58:25:902599836

It shows a US styled data for me but see man date for more refinement. The 2 interesting options:
%N     nanoseconds (000000000..999999999)
%S     second (00..60)

And if you want to use the standard year, month, day format:
$ date +%Y.%m.%d_%H:%M:%S:%N
2023.09.08_12:59:29:709566968

$ date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S
2019-01-19_05:00:00

$ date -d "2019-01-19T05:00:00 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:55:00

$ date -d "2018-12-10 00:00:00 5 hours ago 20 minutes ago 5 seconds ago"
2018年12月09日 星期日 18:39:55 CST
"5 hours ago" subtract 5 hours
"4 hours" add (implicit) 4 hours


指定时区
$ TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_03:00:00

$ TZ=Asia/Colombo date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:30:00

UTC时间
$ TZ=UTC date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S%Z           
2019-01-19_05:00:00UTC

带上debug选项可以看到
TZ=UTC date -d "2019-01-19T05:00:00 - 2 minutes" +%Y-%m-%d_%H:%M:%S%Z --debug


DATE=2023-09-06
for i in {0..5}
do
   NEXT_DATE=$(date +%Y-%m-%d -d "$DATE + $i day")
   echo "$NEXT_DATE"
done

#使用Perl模块来打印时间
perl -MTime::Piece -MTime::Seconds -sE '
my $d = Time::Piece->strptime($mydate, "%Y-%m-%d %H:%M:%S");
($dow, $month, $dom, $hour, $year) = split / +/, $d+ONE_DAY;
my $datex = Time::Piece->strptime("$dow $month $dom $year $hour","%a %b %d %Y %H:%M:%S");
say $datex->strftime("%Y-%m-%dT%H:%M:%S");
' -- -mydate='2023-09-06 06:21:37'