Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1736383
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: 系统运维

2012-03-29 12:39:21

由UNIX内核提供的基本时间服务计算自从Epoch:统一全球时间(Coordinated Universal Time, UTC)1970-1-1 00:00:00至今经过的秒数。在1.10节,我们说过这些秒数用time_t数据类型表示,而我们称它们为日历时间。这些日历时间同时表示时间和日 期。UNIX系统总是和其它操作系统有所区别:a、保留UTC时间而不是本地时间;b、自动完成转换,比如夏令时时间;c、把时间和日期作为单一量存储。


time函数返回当前的时间和日期。



  1. #include <time.h>

  2. time_t time(time_t *calptr);

  3. 成功返回时间值,错误返回-1。


这个时间值总是作为函数的值返回。如果参数是一个非空值,时间值也被存储在calptr指向的地点里。


我们没有说过内核如何初始化当前时间。历史上,在从System V继承下来的实现上,stime函数被调用,而基于BSD的系统使用settimeofday。


SUS没有指定系统如何设置它的当前时间。


gettimeofday函数提供了比time函数更好的精度(精确到微秒)。这对于一些应用程序很重要。



  1. #include <sys/time.h>

  2. int gettimeofday(struct timeval *restrict tp, void *restrict tzp);

  3. 总是返回0。


这个函数定义在SUS的XSI扩展里。tzp的唯一合法值是NULL。其它值会导致未指定的行为。一些平台通过使用tzp支持一个时区的指定,然而这是系统指定的而不是SUS定义的。


gettimeofday函数把以Epoch衡量的当前时间存储在由tp指向的内存里。这个时间被表示为一个timeval结构里,它存储秒数和微秒数:


struct timeval {
  time_t tv_sec;  /* seconds */
  long tv_usec; /* microseconds */
}:


一但我们有了这个计算从Epoch至今的秒数的整型值,我们可以调用其它函数来把它转换成人可读的时间和日期。


localtime和gmtime这两个函数把日历时间转换了一个被称为分解时间(broken-down time)的一个结构体tm。


struct tm {  /* a broken-down time */
  int tm_sec;  /* seconds after the minute: [0 - 60] */
  int tm_min;  /*  minutes after the hour: [0-59] */
  int tm_hour;  /* hours after midnight:[0-23] */
  int tm_mday;  /* day of the month: [1-31] */
  int tm_mon;  /* months since January: [0-11] */
  int tm_year;  /* years since 1900 */
  int tm_wday;  /* days since sunday: [0-6] */
  int tm_yday;  /* days since January 1: [0-365] */
  int tm_isdst;  /* daylight saving time flag: <0, 0, >0 */
};


秒数能大于59的原因是为了允许闰秒(leap second)。注意除了月份日之外的所有域都是基于0的。夏令时标志为正表示夏令时有效,0表示无效,负值表示些信息不可用。


在SUS的前一个版本,双闰秒(double leap seconds)被允许。这样,tm_sec成员的合法范围是0-61。UTC的格式定义不允许双闰秒,所以秒的合法值现在被定义为0-60。



  1. #include <time.h>
  2. struct tm *gmtime(const time_t *calptr);

  3. struct tm *localtime(const time_t *calptr);

  4. 两者都返回分解时间的指针。


localtime和gmtime的区别在于第一个把日历时间转换为本地时间,根据时区和夏令时标志,而后者把日历时间转换成一个表示为UTC的分解时间。


函数mktime接受一个表示为本地时间的分解时间,并把它转换成一个time_t值。



  1. #include <time.h>

  2. time_t mktime(struct tm *tmptr);

  3. 成功返回日历时间,错误返回-1


asctime和ctime函数生产熟悉的26字节字符串,它与date命令的默认输出类似:


2012年 02月 27日 星期一 17:15:51 CST



  1. #include <time.h>

  2. char *asctime(const struct tm *tmptr);

  3. char *ctime(const time_t *calptr);

  4. 两者都返回以null结尾的字符串。


asctime的参数是一个指向分解时间字符串的指针,而ctime的参数是一个指向日历时间的指针。


最后一个时间函数,strftime,是最复杂的。它是一个对于时间值类似于printf的函数。



  1. #include <time.h>

  2. size_t strftime(char *restrict buf, size_t maxsize, const char *restrict format, const struct tm *restrict tmptr);

  3. 如果空间足够返回存储在数组里的字符数,否则返回0。


最后的参数是格式所需的时间值,由一个分解时间值的指针指定。格式化的结构存储在尺寸为maxsize的buf数组里。如果包括终止null的结果的尺寸,可以放入这个缓冲,那么函数返回在buf里存储的字符数,不包括终止null。否则,该函数返回0。


参数format控制这个时间值的格式化。和printf函数相似,转换指示符由一个百分号接着一个特殊的字符给定。格式化字符串的所有其它字符被拷贝到 输出中。一行内的两个百分号在输出中产生单个百分号。不像printf函数,每个指定的转换产生一个不同的固定大小的输出字符串--在格式化字符串里没有 域长度。下表描述了37个ISO C的转换指示符。该表的第三列是Linux下的strftime输出,对应时间日期为Tue Feb 10 18:27:38 EST 2004。


     
格式 描述 例子
%a 缩写的星期名 Tue
%A 完全星期名 Tuesday
%b 缩写的月名 Feb
%B 完全月名 February
%c 日期与时间 Tue Feb 10 18:27:38 2004
%C 年份除以100: [00-99] 20
%d 月内日期:[01-31] 10
%D 日期[MM/DD/YY] 02/10/04
%e 月内日期(单个数字用空格开头)[1-31] 10
%F ISO 8601日期格式[YYYY-MM-DD] 2004-02-10
%g ISO 8601基于星期的年份的后两个数字[00-99] 04
%G ISO 8601基于星期的年份 2004
%h 与%b相同 Feb
%H 一天内的小时(24小时格式):[00-23] 18
%I 一天内的小时(12小时格式):[01-12] 06
%j 一年内的天数[001-366] 041
%m 月份:[01-12] 02
%M 分:[00-59] 27
%n 换行符  
%p AM/PM PM
%r 本地时间(12小时格式) 06:27:38 PM
%R 和“%H:%M”相同 18:27
%S 秒:[00-60] 38
%t 水平制表符  
%T 和“%H:%M:%S”相同 18:27:38
%u ISO 8601星期[周一=1,1-7] 2
%U 周日星期数:[00-53] 06
%V ISO 8601星期数:[01-53] 07
%w 星期:[0=周天,0-6] 2
%W 周一星期数:[00-53] 06
%x 日期 02/10/04
%X 时间 18:27:38
%y 年份后两位:[00-99] 04
%Y 年份 2004
%z UTC以ISO 8601格式的偏移量 -500
%Z 时间区 EST
%% 翻译为一个百分号 %


不明朗的指示符只有%U、%V和%W。%U指示符表示年内的星期数,包含第一个星期天的星期被作为第一个星期。%W指示符表示年内的星期数,包含第一个周 一的是第一个星期。%V指示符不同。如果包含新年一月的第一天的星期有四天或更多天,这个星期被作为第一个星期。不然,它作为去年的最后一个星期。在两种 情况下,周一都作为星期的第一天。


和printf一样,strftime支持了一些转换指示符的修改符。E和O修改符可以用来产生替代格式,如果本地化被支持的话。


一些系统在strftime的格式化字符串时支持额外的,非标准的扩展。


localtime、mktime、ctime和strftime被TZ环境变量影响。如果定义的话,这个环境变量的值被这些函数使用代替默认的时区。如 果变量被定义为空字符串,比如TZ=,那么UTC通常被使用。这个环境变量的值通常是像TZ=EST5EDT的东西,但POSIX.1允许细节地多的指 定。参考SUS的环境变量那一样来得到TZ变量的所有细节。


本节描述的所有的时间和日期函数,除了gettimeofday,都定义在ISO C标准里。然而,POSIX.1加入了TZ环境变量。在FreeBSD 5.2.1、Linux 2.4.2和Mac OS X 10.3上,TZ变量的更多信息可以在tzset手册页上找到。在Solaris 9,这个信息在environ手册页里。

阅读(1187) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~