首页 > 代码库 > APUE学习笔记——6.10 时间与时间例程 time_t

APUE学习笔记——6.10 时间与时间例程 time_t



       Unix提供的最基本的时间服务室日历时间(纪元时间),也就是计算1970年1月1日0时0分0秒到当前的秒数。该秒数用time_t表示。
  1. typedef long time_t; /* 时间值time_t 为长整型的别名*/
     

1、获取/设置时间

1.1 time和time_t

函数time()可以用于获取当前日历时间
  1. #include <time.h>
  2. time_t time(time_t *calptr);
  3. Returns: value of time if OK,?1 on error
      当前时间值(即1970年1月1日0时0分0秒到现在的秒数)保存给calptr指针指向的地址,也作为返回值。

1.2 指定时钟类型

Unix提供指定时钟类型来获取/设置时间的方法。
  1. #include <time.h>
  2. int clock_getres(clockid_t clk_id, struct timespec *res);
  3. int clock_gettime(clockid_t clk_id, struct timespec *tp);
  4. int clock_settime(clockid_t clk_id, const struct timespec *tp);
  5. Link with -lrt.编译时使用链接库lrt
clock_gettime()和clock_settime();函数提供了纳秒级别的时间,并且会根据clk_id的时间类型进行取值。
clock_getres 用于获取时间的分辨率。  clock_gettime()和clock_settime()使用的时间必须是时间分辨率的整数倍,不是整数倍也要切割成整数倍。
clockid_tclk_id用于指定计时时钟的类型,有以下选项:
  1. CLOCK_REALTIME:系统实时时间,使用此选项时功能相当于time(),如果系统时间被用户修改过,则对应的时间相应改变
  2. CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
  3. CLOCK_PROCESS_CPUTIME_ID:本进程运行的CPU时间
  4. CLOCK_THREAD_CPUTIME_ID:本线程运行的CPU时间
  1. struct timespec {
  2. time_t tv_sec; /* seconds */
  3. long tv_nsec; /* nanoseconds */
  4. };

1.3 gettimeofday()与settimeofday()

Unix/Linux提供了微秒级别获取和设置时间的函数gettimeofday()与settimeofday(),但根据man手册的描述,这两个函数已经过时,此处不做介绍。仅列出原型(这两个函数编译需要glibc的支持)
  1. #include <sys/time.h>
  2. int gettimeofday(struct timeval *tv, struct timezone *tz);
  3. int settimeofday(const struct timeval *tv, const struct timezone *tz);

2、时间格式转换

    我们使用time()等函数获取的时间是一个time_t获取的从新纪元开始到当前所经过的秒数,是一个整数值。(calender time)
    我们很多情况下需要将其转换成我们可读的,向时分秒这样的时间(broken down time)。这就需要进行转化。
    时间转换图如 Figure6.9 所示


    我们使用struct tm来保存broken-down time
  1. struct tm { /* a broken-down time */
  2.     int tm_sec;     // 秒 【0~60】 60存在的原因是闰秒的存在
  3.     int tm_min;     //分
  4.     int tm_hour;    //时
  5.     int tm_mday;    //日
  6.     int tm_mon;     //月
  7.     int tm_year;    //年 结构中记录的是从1900至今的年数
  8.     int tm_wday; //星期几 【0~6】
  9.     int tm_yday;    // 一年中第几天
  10.     int tm_isdst; // 夏时制标志
  11. };
夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

    Unix提供了时间格式转换的函数

2.1 time_t与struct tm相互转化


time_t转化成struct tm
  1. #include <time.h>
  2. struct tm *gmtime(const time_t *calptr);
  3. struct tm *localtime(const time_t *calptr);
  4. Both return: pointer to broken-down time,NULLon error
gmtime 转换成国际标准时间
localtime转换成本地时间(考虑到本地时区和夏时制标志)
struct tm转化成time_t
  1. #include <time.h>
  2. time_t mktime(struct tm *tmptr);
  3. Returns: calendar time if OK,?1 on error
example:
  1. #include<stdio.h>
  2. #include <time.h>
  3. #include<sys/time.h>
  4. int main(void)
  5. {
  6. time_t calptr;
  7. if (time(&calptr) == -1)
  8. {
  9. printf("Error: time() failed!\n");
  10. exit(0);
  11. }
  12. printf("Time(time_t) now is: %d\n",(long) calptr);
  13. /*
  14. * 转换成可读到时间
  15. */
  16. struct tm *gmptr; //国际标准时间
  17. struct tm *localptr; //本地时间
  18. /* 转换成国际标准时间 */
  19. printf("\n\n ----------gm time--------------\n");
  20. if (NULL == (gmptr = gmtime(&calptr)))
  21. {
  22. printf("Error: can‘t convert time_t to struct tm by gmtime()!\n");
  23. exit(0);
  24. }
  25. printf("year:%d,\tMonth:%d,\tDay:%d,\tWeek:%d\n", gmptr->tm_year, gmptr->tm_mon, gmptr->tm_mday, gmptr->tm_wday);
  26. printf("Hour:%d,\tMin:%d,\t,sec:%d\n", gmptr->tm_hour, gmptr->tm_min, gmptr->tm_sec);
  27. /* 转换成本地标准时间 */
  28. printf("\n\n ----------local time--------------\n");
  29. if (NULL == (localptr = localtime(&calptr)))
  30. {
  31. printf("Error: can‘t convert time_t to struct tm by localtime()!\n");
  32. exit(0);
  33. }
  34. printf("year:%d,\tMonth:%d,\tDay:%d,\tWeek:%d\n", localptr->tm_year, localptr->tm_mon, localptr->tm_mday, localptr->tm_wday);
  35. printf("Hour:%d,\tMin:%d,\t,sec:%d\n", localptr->tm_hour, localptr->tm_min, localptr->tm_sec);
  36. return 0;
  37. }
运行结果:
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. Time(time_t) now is: 1409207607
  3. ----------gm time--------------
  4. year:114, Month:7, Day:28, Week:4
  5. Hour:6, Min:33, ,sec:27
  6. ----------local time--------------
  7. year:114, Month:7, Day:28, Week:4
  8. Hour:14, Min:33, ,sec:27
东八区,快了8个小时

2.2 转换成格式化字符串

  1. #include <time.h>
  2. size_t strftime(char *restrict buf,size_t maxsize,
  3. const char *restrict format,
  4. const struct tm *restrict tmptr);
  5. size_t strftime_l(char *restrict buf,size_t maxsize,
  6. const char *restrict format,
  7. const struct tm *restrict tmptr,locale_t locale);
  8. ——Both return: number of characters stored in array if room, 0 otherwise
Example:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. int
  5. main(void)
  6. {
  7. time_t t;
  8. struct tm *tmp;
  9. char buf1[16];
  10. char buf2[64];
  11. time(&t);
  12. tmp = localtime(&t);
  13. if (strftime(buf1, 16, "time and date: %r, %a %b %d, %Y", tmp) == 0)
  14. printf("buffer length 16 is too small\n");
  15. else
  16. printf("%s\n", buf1);
  17. if (strftime(buf2, 64, "time and date: %r, %a %b %d, %Y", tmp) == 0)
  18. printf("buffer length 64 is too small\n");
  19. else
  20. printf("%s\n", buf2);
  21. exit(0);
  22. }
  23. ~
运行结果:
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. buffer length 16 is too small
  3. time and date: 02:43:55 PM, Thu Aug 28, 2014

字符串转换成struct tm格式
  1. #include <time.h>
  2. char *strptime(const char *restrictbuf,const char *restrictformat,struct tm *restricttmptr);
  3. Returns: pointer to one character past last character parsed,NULLotherwise

关于转换符号:











       Unix提供的最基本的时间服务室日历时间(纪元时间),也就是计算1970年1月1日0时0分0秒到当前的秒数。该秒数用time_t表示。
  1. typedef long time_t; /* 时间值time_t 为长整型的别名*/
     

1、获取/设置时间

1.1 time和time_t

函数time()可以用于获取当前日历时间
  1. #include <time.h>
  2. time_t time(time_t *calptr);
  3. Returns: value of time if OK,?1 on error
      当前时间值(即1970年1月1日0时0分0秒到现在的秒数)保存给calptr指针指向的地址,也作为返回值。

1.2 指定时钟类型

Unix提供指定时钟类型来获取/设置时间的方法。
  1. #include <time.h>
  2. int clock_getres(clockid_t clk_id, struct timespec *res);
  3. int clock_gettime(clockid_t clk_id, struct timespec *tp);
  4. int clock_settime(clockid_t clk_id, const struct timespec *tp);
  5. Link with -lrt.编译时使用链接库lrt
clock_gettime()和clock_settime();函数提供了纳秒级别的时间,并且会根据clk_id的时间类型进行取值。
clock_getres 用于获取时间的分辨率。  clock_gettime()和clock_settime()使用的时间必须是时间分辨率的整数倍,不是整数倍也要切割成整数倍。
clockid_tclk_id用于指定计时时钟的类型,有以下选项:
  1. CLOCK_REALTIME:系统实时时间,使用此选项时功能相当于time(),如果系统时间被用户修改过,则对应的时间相应改变
  2. CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
  3. CLOCK_PROCESS_CPUTIME_ID:本进程运行的CPU时间
  4. CLOCK_THREAD_CPUTIME_ID:本线程运行的CPU时间
  1. struct timespec {
  2. time_t tv_sec; /* seconds */
  3. long tv_nsec; /* nanoseconds */
  4. };

1.3 gettimeofday()与settimeofday()

Unix/Linux提供了微秒级别获取和设置时间的函数gettimeofday()与settimeofday(),但根据man手册的描述,这两个函数已经过时,此处不做介绍。仅列出原型(这两个函数编译需要glibc的支持)
  1. #include <sys/time.h>
  2. int gettimeofday(struct timeval *tv, struct timezone *tz);
  3. int settimeofday(const struct timeval *tv, const struct timezone *tz);

2、时间格式转换

    我们使用time()等函数获取的时间是一个time_t获取的从新纪元开始到当前所经过的秒数,是一个整数值。(calender time)
    我们很多情况下需要将其转换成我们可读的,向时分秒这样的时间(broken down time)。这就需要进行转化。
    时间转换图如 Figure6.9 所示

    我们使用struct tm来保存broken-down time
  1. struct tm { /* a broken-down time */
  2.     int tm_sec;     // 秒 【0~60】 60存在的原因是闰秒的存在
  3.     int tm_min;     //分
  4.     int tm_hour;    //时
  5.     int tm_mday;    //日
  6.     int tm_mon;     //月
  7.     int tm_year;    //年 结构中记录的是从1900至今的年数
  8.     int tm_wday; //星期几 【0~6】
  9.     int tm_yday;    // 一年中第几天
  10.     int tm_isdst; // 夏时制标志
  11. };
夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

    Unix提供了时间格式转换的函数

2.1 time_t与struct tm相互转化


time_t转化成struct tm
  1. #include <time.h>
  2. struct tm *gmtime(const time_t *calptr);
  3. struct tm *localtime(const time_t *calptr);
  4. Both return: pointer to broken-down time,NULLon error
gmtime 转换成国际标准时间
localtime转换成本地时间(考虑到本地时区和夏时制标志)
struct tm转化成time_t
  1. #include <time.h>
  2. time_t mktime(struct tm *tmptr);
  3. Returns: calendar time if OK,?1 on error
example:
  1. #include<stdio.h>
  2. #include <time.h>
  3. #include<sys/time.h>
  4. int main(void)
  5. {
  6. time_t calptr;
  7. if (time(&calptr) == -1)
  8. {
  9. printf("Error: time() failed!\n");
  10. exit(0);
  11. }
  12. printf("Time(time_t) now is: %d\n",(long) calptr);
  13. /*
  14. * 转换成可读到时间
  15. */
  16. struct tm *gmptr; //国际标准时间
  17. struct tm *localptr; //本地时间
  18. /* 转换成国际标准时间 */
  19. printf("\n\n ----------gm time--------------\n");
  20. if (NULL == (gmptr = gmtime(&calptr)))
  21. {
  22. printf("Error: can‘t convert time_t to struct tm by gmtime()!\n");
  23. exit(0);
  24. }
  25. printf("year:%d,\tMonth:%d,\tDay:%d,\tWeek:%d\n", gmptr->tm_year, gmptr->tm_mon, gmptr->tm_mday, gmptr->tm_wday);
  26. printf("Hour:%d,\tMin:%d,\t,sec:%d\n", gmptr->tm_hour, gmptr->tm_min, gmptr->tm_sec);
  27. /* 转换成本地标准时间 */
  28. printf("\n\n ----------local time--------------\n");
  29. if (NULL == (localptr = localtime(&calptr)))
  30. {
  31. printf("Error: can‘t convert time_t to struct tm by localtime()!\n");
  32. exit(0);
  33. }
  34. printf("year:%d,\tMonth:%d,\tDay:%d,\tWeek:%d\n", localptr->tm_year, localptr->tm_mon, localptr->tm_mday, localptr->tm_wday);
  35. printf("Hour:%d,\tMin:%d,\t,sec:%d\n", localptr->tm_hour, localptr->tm_min, localptr->tm_sec);
  36. return 0;
  37. }
运行结果:
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. Time(time_t) now is: 1409207607
  3. ----------gm time--------------
  4. year:114, Month:7, Day:28, Week:4
  5. Hour:6, Min:33, ,sec:27
  6. ----------local time--------------
  7. year:114, Month:7, Day:28, Week:4
  8. Hour:14, Min:33, ,sec:27
东八区,快了8个小时

2.2 转换成格式化字符串

  1. #include <time.h>
  2. size_t strftime(char *restrict buf,size_t maxsize,
  3. const char *restrict format,
  4. const struct tm *restrict tmptr);
  5. size_t strftime_l(char *restrict buf,size_t maxsize,
  6. const char *restrict format,
  7. const struct tm *restrict tmptr,locale_t locale);
  8. ——Both return: number of characters stored in array if room, 0 otherwise
Example:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. int
  5. main(void)
  6. {
  7. time_t t;
  8. struct tm *tmp;
  9. char buf1[16];
  10. char buf2[64];
  11. time(&t);
  12. tmp = localtime(&t);
  13. if (strftime(buf1, 16, "time and date: %r, %a %b %d, %Y", tmp) == 0)
  14. printf("buffer length 16 is too small\n");
  15. else
  16. printf("%s\n", buf1);
  17. if (strftime(buf2, 64, "time and date: %r, %a %b %d, %Y", tmp) == 0)
  18. printf("buffer length 64 is too small\n");
  19. else
  20. printf("%s\n", buf2);
  21. exit(0);
  22. }
  23. ~
运行结果:
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. buffer length 16 is too small
  3. time and date: 02:43:55 PM, Thu Aug 28, 2014

字符串转换成struct tm格式
  1. #include <time.h>
  2. char *strptime(const char *restrictbuf,const char *restrictformat,struct tm *restricttmptr);
  3. Returns: pointer to one character past last character parsed,NULLotherwise

关于转换符号:











APUE学习笔记——6.10 时间与时间例程 time_t