《unix环境高级编程》 读书笔记 (5)

时间:2021-04-01 22:12:54
目录: http://blog.csdn.net/alex_my/article/details/39346381

date and time



涉及到的函数列出如下,然后再举例运行,输出结果,比较直观。

时间这块资料有限,如果有误,还望指正。

#include <time.h>

time_t time(time_t*tloc);

int clock_getres(clockid_t clk_id, struct timespec* res);
int clock_gettime(clockid_t clk_id, struct timespec* tp);
int clock_settime(clockid_t clk_id, const struct timespec* tp);

////////////////////////////
#include <sys/time.h>

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

////////////////////////////
#include <time.h>

char* asctime(const struct tm* tm);
char* asctime_r(const struct tm* tm, char* buf);

char* ctime(const time_t* timep);
char* ctime_r(const time_t* timep, char* buf);

struct tm* gmtime(const time_t* timep);
struct tm* gmtime_r(const time_t* timep, struct tm* result);

struct tm* localtime(const time_t* timep);
struct tm* localtime_r(const time_t* timep, struct tm* result);

time_t mktime(struct tm* tm);

////////////////////////////
#include <time.h>

size_t strftime(char* s, size_t max, const char* format, const struct tm* tm);

///////////////////////////
#define _XOPEN_SOURCE       /* See feature_test_macros(7) */
#include <time.h>

char* strptime(const char* s, const char* format, struct tm* tm);



#include <time.h>

time_t time(time_t* tloc);

Epoch: 指的是一个特定的时间, 1970年1月1日 00:00:00 UTC

return:
time函数返回从Epoch到当前的秒数,如果参数tloc不为null,还会赋值到tloc中。
如果出错,则会返回-1。

程序用例:

#include <stdio.h>
#include <time.h>

int main(int argc, char* argv[])
{
     time_t t = time(NULL);
     printf("time: %d\n", static_cast<int>(t));

     return 0;
}

输出:

time: 1410606639



#include <time.h>

int clock_getres(clockid_t clk_id, struct timespec* res);
int clock_gettime(clockid_t clk_id, struct timespec* tp);
int clock_settime(clockid_t clk_id, const struct timespec* tp);

return:
如果正常则返回0,错误返回-1。结果均填充在res(tp)中。

timespec的定义:

struct timespec 
{
 time_t   tv_sec;        /* seconds */
     long     tv_nsec;       /* nanoseconds */
};

clk_id用于指定计时时钟的类型,有以下选项:

CLOCK_REALTIME: 系统实时时间,从Epoch计时,可以被用户更改以及adjtime和NTP影响。

CLOCK_REALTIME_COARSE: 系统实时时间,比起CLOCK_REALTIME有更快的获取速度,更低一些的精确度。

CLOCK_MONOTONIC: 从系统启动这一刻开始计时,即使系统时间被用户改变,也不受影响。系统休眠时不会计时。受adjtime和NTP影响。

CLOCK_MONOTONIC_COARSE: 如同CLOCK_MONOTONIC,但有更快的获取速度和更低一些的精确度。受NTP影响。

CLOCK_MONOTONIC_RAW: 与CLOCK_MONOTONIC一样,系统开启时计时,但不受NTP影响,受adjtime影响。

CLOCK_BOOTTIME: 从系统启动这一刻开始计时,包括休眠时间,受到settimeofday的影响。

CLOCK_PROCESS_CPUTIME_ID: 本进程开始到此刻调用的时间。

CLOCK_THREAD_CPUTIME_ID: 本线程开始到刺客调用的时间。


clock_getres获取指定类型时钟的精确度。

clock_gettime和clock_settime取得和设置clk_id指定的时间。

看过用例就明白了。

程序用例:clock_getres和clock_gettime

#include <stdio.h>
#include <time.h>

static void ShowTime(const char* desc, const timespec* res)
{
     printf("%s: \t %d\t %d\n", desc, res->tv_sec, res->tv_nsec);
}

static void TestTime(clockid_t clk_id)
{
     struct timespec res;

     clock_getres(clk_id, &res);
     ShowTime("clock_getres", &res);

     clock_gettime(clk_id, &res);
     ShowTime("clock_gettime", &res);
}

int main(int argc, char* argv[])
{
     // 为了方便阅读,假设函数调用成功
     printf("CLOCK_REALTIME: \n");
     TestTime(CLOCK_REALTIME);

     printf("\n\nCLOCK_REALTIME_COARSE:\n");
     TestTime(CLOCK_REALTIME_COARSE);

     printf("\n\nCLOCK_MONOTONIC:\n");
     TestTime(CLOCK_MONOTONIC);

     return 0;
}

输出:

CLOCK_REALTIME: 
clock_getres: 0 1
clock_gettime: 1410750427 192193358


CLOCK_REALTIME_COARSE:
clock_getres: 0 1000000
clock_gettime: 1410750427 191422911


CLOCK_MONOTONIC:
clock_getres: 0 1
clock_gettime: 4269 364748226


#include <sys/time.h>

int gettimeofday(struct timeval* restrict tp, void* restrict tzp);
 
return:
一直返回0         

参数2 tzp必须为NULL

struct timeval
{
     time_t tv_sec;       //秒 [long int]
     suseconds_t tv_usec; //微秒 [long int]
}

程序用例: 

#include <stdio.h>
#include <sys/time.h>

int main(int argc, char* argv[])
{
     timeval tp;
     int ret = gettimeofday(&tp, NULL);
     printf("ret: %d\t sec: %d\t usec: %d\n", ret, tp.tv_sec, tp.tv_usec);

     return 0;
}

输出:

ret: 0 sec: 1410752524 usec: 95274



char* asctime(const struct tm* tm);
char* asctime_r(const struct tm* tm, char* buf); // buf: 26 bytes at least

char* ctime(const time_t* timep);
char* ctime_r(const time_t* timep, char* buf);   // buf: 26 bytes at least

struct tm* gmtime(const time_t* timep);
struct tm* gmtime_r(const time_t* timep, struct tm* result);

struct tm* localtime(const time_t* timep);
struct tm* localtime_r(const time_t* timep, struct tm* result);

time_t mktime(struct tm* tm);

tm定义:

struct tm 
{
     int tm_sec;         /* seconds */
     int tm_min;         /* minutes */
     int tm_hour;        /* hours */
     int tm_mday;        /* day of the month */
     int tm_mon;         /* month */
     int tm_year;        /* year */
     int tm_wday;        /* day of the week */
     int tm_yday;        /* day in the year */
     int tm_isdst;       /* daylight saving time */ /* 是否是夏令制 */

     /** the glibc version of struct tm has additional fields:
     /** long tm_gmtoff;
     /** const char* tm_zone;
      */
};

asctime/asctime_r      : 把tm所表示的日期和时间转为字符串, 且会自动转为本地时区
ctime/ctime_r          : 把日期和时间转为字符串
gmtime/gmtime_r        : 把time_t转换为tm,未经时区转换
localtime/localtime_r  : 把time_t转换为tm,转为本地时区
mktime                 : 将tm转换为time_t,UTC

以下示例展示了以上时间的用法:

#include <stdio.h>
#include <time.h>
#include <sys/time.h>

static void ShowTM(const char* desc, const tm* t)
{
     printf("%s:\n", desc);
     printf("%d-%02d-%02d %02d:%02d:%02d\n", 
                    t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
     printf("yday: %d \t wday: %d \t isdst: %d\n\n", 
                    t->tm_yday, t->tm_wday, t->tm_isdst);
}

int main(int argc, char* argv[])
{
     // time
     time_t t = time(NULL);
     printf("time: %d\n\n", static_cast<int>(t));

     // ctime and ctime_r
     char* c1 = ctime(&t);
     printf("ctime: c1: %s\n", c1);

     char c20[64];
     char* c2 = ctime_r(&t, c20);
     printf("ctime_r: c2: %s \t c20: %s \n\n");

     // gmtime and gmtime_r
     tm* t1 = gmtime(&t);
     ShowTM("gmtime-t1", t1);

     tm t20;
     tm* t2 = gmtime_r(&t, &t20);
     ShowTM("gmtime_r-t2", t2);
     ShowTM("gmtime_r-t20", &t20);

     // localtime and localtime_r
     tm* t3 = localtime(&t);
     ShowTM("localtime-t3", t3);

     tm t40;
     tm* t4 = localtime_r(&t, &t40);
     ShowTM("localtime_r-t4", t4);
     ShowTM("localtime_r-t40", &t40);

     // asctime and asctime_r
     char* asc1 = asctime(t1);
     printf("asctime-gmtime: %s\n", asc1);

     char asc20[128];
     char* asc2 = asctime_r(t1, asc20);
     printf("asctime-gmtime: asc2: %s \t asc20: %s\n", asc2, asc20);

     char* asc3 = asctime(t3);
     printf("asctime-localtime: %s\n", asc3);

     char asc40[128];
     char* asc4 = asctime_r(t3, asc40);
     printf("asctime-localtime: asc4: %s \t asc40: %s\n", asc4, asc40);

     // mktime
     time_t mkt1 = mktime(t1);
     printf("mktime-gmtime: %d\n\n", static_cast<int>(mkt1));

     time_t mkt2 = mktime(t3);
     printf("mktime-localtime: %d\n", static_cast<int>(mkt2));

     return 0;
}

输出:

time: 1410770573

ctime: c1: Mon Sep 15 16:42:53 2014

ctime_r: c2: 
   c20:  

gmtime-t1:
114-08-15 08:42:53
yday: 257   wday: 1   isdst: 0

gmtime_r-t2:
114-08-15 08:42:53
yday: 257   wday: 1   isdst: 0

gmtime_r-t20:
114-08-15 08:42:53
yday: 257   wday: 1   isdst: 0

localtime-t3:
114-08-15 16:42:53
yday: 257   wday: 1   isdst: 0

localtime_r-t4:
114-08-15 16:42:53
yday: 257   wday: 1   isdst: 0

localtime_r-t40:
114-08-15 16:42:53
yday: 257   wday: 1   isdst: 0

asctime-gmtime: Mon Sep 15 16:42:53 2014

asctime-gmtime: asc2: Mon Sep 15 16:42:53 2014
   asc20: Mon Sep 15 16:42:53 2014

asctime-localtime: Mon Sep 15 16:42:53 2014

asctime-localtime: asc4: Mon Sep 15 16:42:53 2014
   asc40: Mon Sep 15 16:42:53 2014

mktime-gmtime: 1410770573

mktime-localtime: 1410770573



#include <time.h>

size_t strftime(char* s, size_t max, const char* format, const struct tm* tm);

strftime: 将tm按照format的格式,格式化输出到大小为max的字符串s中。

格式部分字符:

%a: 周几的英文缩写。
%A: 周几的英文全称。
%b: 月份的英文缩写。
%B: 月份的英文全称。
%c: 日期和时间, Tue Feb 10 19:45:20 2014。
%C: 年/100 [00, 99]。
%d: 每月的第几天 [01, 31] 。
%D: 日期 MM/DD/YY 09/15/14。
%e: 每月的第几天[1, 31], 个位数前添加空格。
%F: ISO 8601 日期格式 YYYY-MM-DD 2014-09-15。
%g: ISO 8601 年的最后2位,基于周的年 [00,99]。
%G: ISO 8601 基于周的年, 2014。
%h: 与%b相同。
%H: 小时(24小时制) [00, 23]。
%I: 小时(12小时制) [01, 12]。
%j: 一年的第几天, [000, 366]。
%m: 月份 [01, 12]。
%M: 分钟 [00, 59]。
%n: 换行符。
%p: AM/PM。
%r: 本地时间(12小时制) 09:15:21 PM。
%R: 与 %H:%M相同, 18:27。
%S: 秒 [00, 60]。
%t: 水平制表符。
%T: 与 %H:%M:%S相同。
%u: ISO 8601 [Monday = 1, 7]。
%U: 以周日作为标准,一年的第几周。在第一月第一周,如果该周一半(4天)以上属于该年,则作为本年第一周,否则做为上一年最后一周。
%V: ISO 8601 周数 [01, 53]。
%w: 一周的第几天 [Sunday = 0, 6]。
%W: 以星期一做为标准,一年的第几周。判断方法如同%U。
%x: 日期 09/15/14
%X: 时间 19:45:20
%y: 年的最后两位 [00, 99] 14
%Y: 年 2014
%z: ISO 8601格式的UTC偏移量
%Z: 时区名
%%: %


程序用例:

#include <stdio.h>
#include <time.h>

int main(int argc, char* argv[])
{
     char desc[128] = {0};
     time_t curr = time(NULL);
     tm* t = localtime(&curr);
     int n = strftime(desc, 128, "It is: %D\n", t);
     printf("n: %d\t %s\n", n, desc);

     return 0;
}

输出:
n: 16  It is: 09/15/14



#include <time.h>

char* strptime(const char* s, const char* format, struct tm* tm);

strptime: 按照特定时间格式将字符串转换为时间类型。

return:

成功返回s的最后位置。失败返回空指针。

程序用例:

#include <stdio.h>
#include <time.h>

int main(int argc, char* argv[])
{
     tm t;
     char buffer[256] = {0};

     strptime("2014-09-15 21:44:45", "%Y-%m-%d %H:%M:%S", &t);
     strftime(buffer, 256, "%d %b %Y %H:%M", &t);
     puts(buffer);

     return 0;
}

输出:

15 Sep 2014 21:44