Chapter 11 Working with Dates and Times

1.1 Formatting Dates for Display

Use the date command with a strftime format specification.

# Setting environment variables can be helpful in scripts:
$ STRICT_ISO_8601='%Y-%m-%dT%H:%M:%S%z' # http://greenwichmeantime.com/info/iso.htm
$ ISO_8601='%Y-%m-%d %H:%M:%S %Z' # Almost ISO-8601, but more human-readable
$ ISO_8601_1='%Y-%m-%d %T %Z' # %T is the same as %H:%M:%S
$ DATEFILE='%Y%m%d%H%M%S' # Suitable for use in a file name
[maxwell@MaxwellDBA Day0801]$ STRICT_ISO_8601='%Y-%m-%dT%H:%M:%S%z'
[maxwell@MaxwellDBA Day0801]$ ISO_8601='%Y-%m-%d %H:%M:%S %Z'
[maxwell@MaxwellDBA Day0801]$ ISO_8601_01='%Y-%m-%d %T %Z'
[maxwell@MaxwellDBA Day0801]$ DATEFILE='%Y%m%d%H%M%S'
[maxwell@MaxwellDBA Day0801]$ date "+$IS0_8601"
2022-08-01 07:50:35 CST
[maxwell@MaxwellDBA Day0801]$ gawk "BEGIN {print strftime(\"$ISO_8601\")}"
2022-08-01 07:50:49 CST
[maxwell@MaxwellDBA Day0801]$ # Same as previous $ISO_8601
[maxwell@MaxwellDBA Day0801]$ date '+%Y-%m-%d %H:%M:%S %Z'
2022-08-01 07:52:08 CST
[maxwell@MaxwellDBA Day0801]$ date "+Program starting at: $ISO_8601"
Program starting at: 2022-08-01 07:52:54 CST
[maxwell@MaxwellDBA Day0801]$ printf "%b" "Program starting at: $(date '+$ISO_8601')\n"
Program starting at: $ISO_8601
[maxwell@MaxwellDBA Day0801]$ echo "I can rename a file like this: mv file.log file_$(date +$DATEFILE).log"
I can rename a file like this: mv file.log file_20220801075507.log
[maxwell@MaxwellDBA Day0801]$ 

1.2 Supplying a Default Date

Using the GNU date command,assign the most likely date to a variable, then allow the user to change it.

[maxwell@MaxwellDBA Day0801]$ cat default_date.sh
#!/usr/bin/env bash
# cookbook filename: default_date.sh
#Use Noon time to prevent a script running around midnight and a clock a few seconds off from causing off by one day errors.
START_DATE=$(date -d 'last week Monday 12:00:00' '+%Y-%m-%d')
while [ 1 ]; do
     printf "%b" "The starting date is $START_DATE,is that correct? (Y/new date) "
     read answer

     # Anything other than ENTER,"Y" or "y" is validated as a new date could use "[Yy]*" to allow the user to spell out "yes"...
     # validate the new date format as: CCYY-MM-DD
     case "$answer" in
        [Yy]) break
            ;;
        [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])
            printf "%b" "Overriding $START_DATE with $answer\n"
            START_DATE="$answer"
            ;;

        *)  printf "%b" "Invalid date, please try again...\n"
            ;;
     esac
done

END_DATE=$(date -d "$DATE_DATE +7 days" '+%Y-%m-%d')

echo "START_DATE: $START_DATE"
echo "END_DATE:   $END_DATE"
[maxwell@MaxwellDBA Day0801]$ 

1.3 Automating Date Ranges

The -d option allow you to specify a specific date instead of using now,but not all date commands support it.

[maxwell@MaxwellDBA Day0801]$ date '+%Y-%m-%d %H:%M:%S %Z'
2022-08-01 09:34:58 CST
[maxwell@MaxwellDBA Day0801]$ date -d 'today' '+%Y-%m-%d %H:%M:%S %z'
2022-08-01 09:35:42 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'yesterday' '+%Y-%m-%d %H:%M:%S %z'
2022-07-31 09:35:56 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'tomorrow' '+%Y-%m-%d %H:%M:%S %z'
2022-08-02 09:36:08 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'Monday' '+%Y-%m-%d %H:%M:%S %z'
2022-08-01 00:00:00 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'this Monday' '+%Y-%m-%d %H:%M:%S %z'
2022-08-01 00:00:00 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'last Monday' '+%Y-%m-%d %H:%M:%S %z'
2022-07-25 00:00:00 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'next Monday' '+%Y-%m-%d %H:%M:%S %z'
2022-08-08 00:00:00 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'last week' '+%Y-%m-%d %H:%M:%S %z'
2022-07-25 09:54:57 +0800
[maxwell@MaxwellDBA Day0801]$ date -d 'next week' '+%Y-%m-%d %H:%M:%S %z'
2022-08-08 09:55:11 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '2 weeks' '+%Y-%m-%d %H:%M:%S %z'
2022-08-15 09:55:30 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '-2 weeks' '+%Y-%m-%d %H:%M:%S %z'
2022-07-18 09:55:39 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '2 weeks ago' '+%Y-%m-%d %H:%M:%S %z'
2022-07-18 09:55:54 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '+4 days' '+%Y-%m-%d %H:%M:%S %z'
2022-08-05 09:56:27 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '-6 days' '+%Y-%m-%d %H:%M:%S %z'
2022-07-26 09:56:40 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '2022-08-01 +12 days' '+%Y-%m-%d %H:%M:%S %z'
2022-08-13 00:00:00 +0800
[maxwell@MaxwellDBA Day0801]$ date -d '3 months 1 day' '+%Y-%m-%d %H:%M:%S %z'
2022-11-02 09:57:59 +0800
[maxwell@MaxwellDBA Day0801]$ date '+%a %Y-%m-%d'
Mon 2022-08-01
[maxwell@MaxwellDBA Day0801]$ date -d 'today''+%a %Y-%m-%d'
date: invalid date ‘today+%a %Y-%m-%d’
[maxwell@MaxwellDBA Day0801]$ date -d 'today' '+%a %Y-%m-%d'
Mon 2022-08-01
[maxwell@MaxwellDBA Day0801]$ date -d 'Saturday' '+%a %Y-%m-%d'
Sat 2022-08-06
[maxwell@MaxwellDBA Day0801]$ date -d 'last Saturday' '+%a %Y-%m-%d'
Sat 2022-07-30
[maxwell@MaxwellDBA Day0801]$ date -d 'this Saturday' '+%a %Y-%m-%d'
Sat 2022-08-06
[maxwell@MaxwellDBA Day0801]$ date -d 'next Saturday' '+%a %Y-%m-%d'
Sat 2022-08-06
[maxwell@MaxwellDBA Day0801]$ date -d 'this week Friday' '+%a %Y-%m-%d'
Fri 2022-08-05
[maxwell@MaxwellDBA Day0801]$ 

The article presents five shell functions:

pn_month
Previous and next x months relative to the given month
end_month
End of month of the given month
pn_day
Previous and next x days of the given day
cur_weekday
Day of week for the given day
pn_weekday
Previous and next x day of weeks relative to the given day
And these were added not long before this book went to press:
pn_day_nr
(Non-recursive) Previous and next x days of the given day
days_between
Number of days between two dates

1.4 Converting Dates and Times to Epoch Seconds

Use the GNU date command with the nonstandard -d option and a standard %s format:

[maxwell@MaxwellDBA Day0801]$ # "Now" is easy
[maxwell@MaxwellDBA Day0801]$ date '+%s'
1659319857
[maxwell@MaxwellDBA Day0801]$ # Some other time needs the non-standard -d
[maxwell@MaxwellDBA Day0801]$ date -d '2022-08-01 12:00:00 +0000' '+%s'
1659355200
[maxwell@MaxwellDBA Day0801]$ perl -e 'print time, qq(\n);'
1659319953
[maxwell@MaxwellDBA Day0801]$ # Same as above
[maxwell@MaxwellDBA Day0801]$ perl -e 'use Time::Local; print timelocal(localtime()). qq(\n);'
1659320017
[maxwell@MaxwellDBA Day0801]$ perl -e 'use POSIX qw(strftime); print strftime("%s",localtime()). qq(\n);'
1659320091
[maxwell@MaxwellDBA Day0801]$ # The given time is in local time
[maxwell@MaxwellDBA Day0801]$ perl -e 'use Time::Local; print timelocal("49","59","06","05","10","105") . qq(\n);'
1131145189
[maxwell@MaxwellDBA Day0801]$ # The given time is in UTC time
[maxwell@MaxwellDBA Day0801]$ perl -e 'use Time::Local; print timegm("49","59","06","05","10","105") . qq(\n);'
1131173989
[maxwell@MaxwellDBA Day0801]$ 

1.5 Converting Epoch Seconds to Dates and Times

[maxwell@MaxwellDBA Day0801]$ EPOCH='1131173989'
[maxwell@MaxwellDBA Day0801]$ date -d '2022-08-01 UTC $EPOCH seconds' '+%Y-%m-%d %T %z'
date: invalid date ‘2022-08-01 UTC $EPOCH seconds’
[maxwell@MaxwellDBA Day0801]$ date -d '2022-08-01 UTC $EPOCH seconds' +'%Y-%m-%d %T %z'
date: invalid date ‘2022-08-01 UTC $EPOCH seconds’
[maxwell@MaxwellDBA Day0801]$ date -d '2022-08-01 UTC $EPOCH seconds' + '%Y-%m-%d %T %z'
date: extra operand ‘%Y-%m-%d %T %z’
Try 'date --help' for more information.
[maxwell@MaxwellDBA Day0801]$ date -d "1970-01-01 UTC $EPOCH seconds" +"%Y-%m-%d %T %z"
2005-11-05 14:59:49 +0800
[maxwell@MaxwellDBA Day0801]$ date -d "2022-08-01 UTC $EPOCH seconds" +"%Y-%m-%d %T %z"
2058-06-05 14:59:49 +0800
[maxwell@MaxwellDBA Day0801]$ date --utc --date "2022-08-01 $EPOCH seconds" +"%Y-%m-%d %T %z"
2058-06-05 06:59:49 +0000
[maxwell@MaxwellDBA Day0801]$ perl -e "print scalar(gmtime($EPOCH)), qq(\n);"    #UTC
Sat Nov  5 06:59:49 2005
[maxwell@MaxwellDBA Day0801]$ perl -e "print scalar(localtime($EPOCH)), qq(\n);"    #Your local time
Sat Nov  5 14:59:49 2005
[maxwell@MaxwellDBA Day0801]$  perl -e "use POSIX qw(strftime); print strftime('%Y-%m-%d %H:%M:%S',
> localtime($EPOCH)), qq(\n);"
2005-11-05 14:59:49
[maxwell@MaxwellDBA Day0801]$ 

1.6 Getting Yesterday or Tomorrow with Perl

[maxwell@MaxwellDBA Day0801]$ # Yesterday at this same time (note subtraction)
[maxwell@MaxwellDBA Day0801]$ perl -e "use POSIX qw(strftime); print strftime('%Y-%m-%d', localtime(time - 86400)), qq(\n);"
2022-07-31
[maxwell@MaxwellDBA Day0801]$ # Tomorrow at this same time (note addition)
[maxwell@MaxwellDBA Day0801]$ perl -e "use POSIX qw(strftime); print strftime('%Y-%m-%d', localtime(time + 86400)),qq(\n);"
2022-08-02
[maxwell@MaxwellDBA Day0801]$ 

1.7 Figuring Out Date and Time Arithmetic

[maxwell@MaxwellDBA Day0801]$ CORRECTION='172800' # 2 days worth of seconds
[maxwell@MaxwellDBA Day0801]$ # Code to extract the date portion from the data into $bad_date go here
[maxwell@MaxwellDBA Day0801]$ # Suppose it's this:
[maxwell@MaxwellDBA Day0801]$ bad_date='Jan 2 05:13:05' # syslog formated date
[maxwell@MaxwellDBA Day0801]$ # Convert to Epoch using GNU date
[maxwell@MaxwellDBA Day0801]$ bad_epoch=$(date -d "$bad_date" '+%s')
[maxwell@MaxwellDBA Day0801]$ # Apply correction
[maxwell@MaxwellDBA Day0801]$ good_epoch=$(( bad_epoch + $CORRECTION))
[maxwell@MaxwellDBA Day0801]$ # Make corrected date human-readable
[maxwell@MaxwellDBA Day0801]$ good_date=$(date -d "2022-08-01 UTC $good_epoch seconds")    # GNU Date
[maxwell@MaxwellDBA Day0801]$ good_date_iso=$(date -d "1970-01-01 UTC $good_epoch seconds" +'%Y-%m-%d %T') # GNU
[maxwell@MaxwellDBA Day0801]$ echo "bad_date:       $bad_date"
bad_date:       Jan 2 05:13:05
[maxwell@MaxwellDBA Day0801]$ echo "bad_epoch:       $bad_epoch"
bad_epoch:       1641071585
[maxwell@MaxwellDBA Day0801]$ echo "Correction:       +$CORRECTION"
Correction:       +172800
[maxwell@MaxwellDBA Day0801]$ echo "good_epoch:       +$good_epoch"
good_epoch:       +1641244385
[maxwell@MaxwellDBA Day0801]$ echo "good_date:       +$good_date"
good_date:       +Sat Aug  4 05:13:05 CST 2074
[maxwell@MaxwellDBA Day0801]$ echo "good_date_iso:       $good_date_iso"
good_date_iso:       2022-01-04 05:13:05
[maxwell@MaxwellDBA Day0801]$ 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值