1.9 获取、设置日期和延时

很多应用程序需要以不同的格式打印日期,设置日期和时间,以及根据日期和时间执行操作。延时通常用于在程序执行过程中提供一段等待时间(比如1秒钟)。比如在每隔五秒钟执行一次监视任务的这类脚本中,则需要掌握如何在程序中加入延时。这则攻略会告诉你怎么处理日期以及延时。

1.9.1 预备知识

我们能够以多种格式打印日期,也可以在命令行中设置日期。在类UNIX系统中,日期被存储为一个整数,其大小为自世界标准时间11970年1月1日0时0分0秒2起所流逝的秒数。这种计时方式称之为纪元时或UNIX时间。来看看如何读取和设置它们吧。

1 UTC(Coordinated Universal Time),又称世界标准时间或世界协调时间。UTC是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。

2 UNIX认为UTC 1970年1月1日0点是纪元时间。POSIX标准推出后,这个时间也被称为POSIX时间。

1.9.2 实战演练

读取日期:

  1. $ date
  2. Thu May 20 23:09:04 IST 2010

打印纪元时:

  1. $ date +%s
  2. 1290047248

纪元时被定义为从世界标准时间1970年1月1日0时0分0秒起至当前时刻的总秒数,不包括闰秒3。当计算两个日期或两段时间的差值时,纪元时很有用处。你可以很容易得出两个特定时间戳的纪元时,并计算出两者之间的差值,由此就能知道两个日期之间相隔了多少秒。

3 国际原子时的误差为每日数纳秒,而世界时的误差为每日数毫秒。针对这种情况,一种称为世界标准时间的折衷时标于1972年面世。为确保UTC与世界时相差不会超过0.9秒,在有需要的情况下会在UTC内加上正或负闰秒,因此UTC与国际原子时之间会出现若干整数秒的差别。位于巴黎的国际地球自转事务中央局负责决定何时加入闰秒。

我们可以从给定格式的日期串中得出对应的纪年时。你在输入时有多种日期格式可供选择。如果你要从系统日志中或者其他任何标准应用程序生成的输出中获取日期,那就完全不用烦心日期格式的问题。要将日期串转换成纪元时,只需要输入如下代码:

  1. $ date --date "Thu Nov 18 08:07:21 IST 2010" +%s
  2. 1290047841

选项 --date用于提供日期串作为输入。但我们可以使用任意的日期格式化选项来打印输出。将日期串作为输入能够用来获知给定的日期是星期几。

例如:

  1. $ date --date "Jan 20 2001" +%A
  2. Saturday

表1-1是一份日期格式字符串列表。

表 1-1

日期内容 格  式
星期 %a(例如:Sat)
%A(例如:Saturday)
%b(例如:Nov)
%B(例如:November)
%d(例如:31)
固定格式日期(mm/dd/yy) %D(例如:10/18/10)
%y(例如:10)
%Y(例如:2010)
小时 %I%H(例如:08)
分钟 %M(例如:33)
%S(例如:10)
纳秒 %N(例如:695208515)
UNIX纪元时(以秒为单位) %s(例如:1290049486)

用格式串结合 + 作为date命令的参数,可以按照你的选择打印出对应格式的日期。例如:

  1. $ date "+%d %B %Y"
  2. 20 May 2010

设置日期和时间:

  1. # date -s "格式化的日期字符串"

例如:

  1. # date -s "21 June 2009 11:01:22"

有时候,我们需要检查一组命令所花费的时间,那就可以采用下面的方式:

  1. #!/bin/bash
  2. #文件名: time_take.sh
  3. start=$(date +%s)
  4. commands;
  5. statements;
  6. end=$(date +%s)
  7. difference=$(( end - start))
  8. echo Time taken to execute commands is $difference seconds.

另一种方法则是使用timescriptpath来得到执行脚本所使用的时间。

1.9.3 补充内容

编写以循环方式运行的监视脚本时,设置时间间隔是必不可少的。让我们来看看如何生成延时。

在脚本中生成延时

为了在脚本中推迟执行一段时间,可以使用sleep

  1. $ sleep no_of_seconds.

例如,下面的脚本就使用tputsleep从0开始计数到40:

  1. #!/bin/bash
  2. #Filename: sleep.sh
  3. echo -n Count:
  4. tput sc
  5. count=0;
  6. while true;
  7. do
  8. if [ $count -lt 40 ];
  9. then let count++;
  10. sleep 1;
  11. tput rc
  12. tput ed
  13. echo -n $count;
  14. else exit 0;
  15. fi
  16. done

在上面的例子中,变量count初始化为0,随后每循环一次便增加1。echo语句打印出count的值。我们用tput sc存储光标位置。在每次循环中,我们通过恢复之前存储的光标位置,在终端中打印出新的count值。恢复光标位置的命令是tput rctput ed清除从当前光标位置到行尾之间的所有内容,使得旧的count值可以被清除并写入新值。循环内的1秒钟延时是通过sleep命令来实现的。