• C++时间操作


    C支持的日常时间格式或种类

    1、时间值 time_t

    时间值是指从1970-01-01 00:00:00 +0000 (UTC) 这个时间点开始到当前时间的秒数。
    在C语言中,用time_t来表示一个秒数,查看头文件可以发现time_t是对long的一个重定义而已。
    相关函数:time()

    2、时间详情 struct tm

    有了具体的时间值time_t,但存在着阅读和理解不方便的问题,所以希望可以把时间值转化为相应的年、月、日、时、分、秒等数据。
    对应的结构体为struct tm。如下代码:

     1 struct tm {
     2    int tm_sec;    /* 秒,取值范围(0~59),但当遇到闰秒时则会有60秒的取值。 */
     3    int tm_min;    /* 分钟数,取值范围(0-59) */
     4    int tm_hour;   /* 小时数,取值范围(0-23) */
     5    int tm_mday;   /* 当天在这个月中是第几天,取值范围(1-31) */
     6    int tm_mon;    /* 当前月份是第几个月,取值范围(0-11) */
     7    int tm_year;   /* 从1900年开始至今的年数,即(Year - 1900)的值 */
     8    int tm_wday;   /* 当天在本周是第几天,取值范围(0-6, Sunday = 0) */
     9    int tm_yday;   /* 当天在今年是第几天,取值范围(0-365, 1 Jan = 0) */
    10    int tm_isdst;  /* 夏令时标记,值大于0表示夏令时生效;等于0表示夏令时失效;小于0表示数据不可用。 */
    11    char *tm_zone; /* 时区名称,根据系统不同可能不被声明或不同全名。 */
    12 };

    相关函数:localtime()、gmtime()

    3、时间字符串 char *

    有了年、月、日等具体的数据,C也提供函数将数据转为转为可视的、有意义的字符串。
    相关函数:

    固定格式时间文本:ctime()、asctime()

    自定义格式时间文本: strftime()

    日常时间函数的调用关系

    获取当前时间值

    time_t time(time_t *t);
    time_t mktime(struct tm *tm);
    time()可以从当前系统中获取时间值并返回,如果参数t不为NULL,则时间值同样也会存储中t中。
    如果函数执行异常,则返回-1,可通过errno查询出错原因。
    mktime()则是将struct tm逆解析为time_t的函数。
    如果参数tm是由用户自己组装的,则tm中的tm_wdaytm_yday会在本函数执行后根据tm中的tm_year``tm_mon…等字段计算为真实的值。

    例子1:

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 int main ()
     5 {
     6   time_t seconds;
     7 
     8   seconds = time(NULL);
     9   printf("自 1970-01-01 起的小时数 = %ld
    ", seconds/3600);
    10   
    11   return(0);
    12 }

    运行结果:

    自 1970-01-01 起的小时数 = 420254

    例子2:

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 int main ()
     5 {
     6    int ret;
     7    struct tm info;
     8    char buffer[80];
     9 
    10    info.tm_year = 2001 - 1900;
    11    info.tm_mon = 7 - 1;
    12    info.tm_mday = 4;
    13    info.tm_hour = 0;
    14    info.tm_min = 0;
    15    info.tm_sec = 1;
    16    info.tm_isdst = -1;
    17 
    18    ret = mktime(&info);
    19    if( ret == -1 )
    20    {
    21        printf("错误:不能使用 mktime 转换时间。
    ");
    22    }
    23    else
    24    {
    25       strftime(buffer, sizeof(buffer), "%c", &info );
    26       print(buffer);
    27    }
    28 
    29    return(0);
    30 }

    运行结果:

    Wed Jul 4 00:00:01 2001

    获取时间详情

    时间详情也就是上文所说的struct tm,manual中也把struct tm称为broken-down time。相关函数:

    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);

    gmtime()localtime()都可以把时间值转换为时间详情,两者的区别在于gmtime()所得到的结果是世界标准时间Coordinated Universal Time (UTC);而localtime()获取的是本地时间。以北京时间为例,gmtime()得到的结果比localtime()要提前(早)8小时。

    gmtime_r()localtime_r()分别是gmtime()localtime()的可重入实现版本。

    为什么有了localtime()还要有其他两个函数呢,因为localtime并不是线程安全的,观察localtime()localtime_r()的调用发现,localtime在使用时,我们只需定义一个指针,并不需要为指针申请空间,而指针必须要指向内存空间才可以使用,其实申请空间的动作由函数自己完成,这样在多线程的情况下,如果有另一个线程调用了这个函数,那么指针指向的struct tm结构体的数据就会改变。在localtime_s()localtime_r()调用时,定义的是struct tm的结构体,获取到的时间已经保存在struct tm中,并不会受其他线程的影响。

    当函数执行错误时,则返回NULL,可通过errno查询出错原因。

    例子1:

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 #define BST (+1)
     5 #define CCT (+8)
     6 
     7 int main ()
     8 {
     9 
    10    time_t rawtime;
    11    struct tm *info;
    12 
    13    time(&rawtime);
    14    /* 获取 GMT 时间 */
    15    info = gmtime(&rawtime );
    16    
    17    printf("当前的世界时钟:
    ");
    18    printf("伦敦:%2d:%02d
    ", (info->tm_hour+BST)%24, info->tm_min);
    19    printf("中国:%2d:%02d
    ", (info->tm_hour+CCT)%24, info->tm_min);
    20 
    21    return(0);
    22 }

    运行结果:

    当前的世界时钟:
    伦敦:15:58
    中国:22:58

    例子2:

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 int main ()
     5 {
     6    time_t rawtime;
     7    struct tm *info;
     8    char buffer[80];
     9 
    10    time( &rawtime );
    11 
    12    info = localtime( &rawtime );
    13    printf("当前的本地时间和日期:%s", asctime(info));
    14 
    15    return(0);
    16 }

    运行结果:

    当前的本地时间和日期:Sun Dec 10 22:57:38 2017

    例子3:

     1 #include <stdio.h>  
     2 #include <time.h>  
     3   
     4 int main()  
     5 {  
     6     time_t time_seconds = time(0);  
     7     struct tm now_time;  
     8     localtime_r(&time_seconds, &now_time);  
     9   
    10     printf("%d-%d-%d %d:%d:%d
    ", now_time.tm_year + 1900, now_time.tm_mon + 1,  
    11         now_time.tm_mday, now_time.tm_hour, now_time.tm_min, now_time.tm_sec);  
    12 } 

    运行结果:

    2017-12-11 14:28:11

    格式化的时间字符串

    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);

    asctime()能直接从时间详情中计算出时间字符串,该字符串包含字符串终止符,计算出来的时间字符串格式是固定的,示例为:Wed Jun 30 21:49:08 1993
    ctime()则是asctime(localtime(time_t))的封装实现。

    asctime_r()ctime_r()分别是asctime()ctime()的可重入实现版本。

    注意:以上函数返回的字符串都会包含换行符

    例子1:

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 int main ()
     5 {
     6    time_t curtime;
     7 
     8    time(&curtime);
     9 
    10    printf("当前时间 = %s", ctime(&curtime));
    11 
    12    return(0);
    13 }

    运行结果:

    当前时间 = Sun Dec 10 22:58:54 2017

    例子2:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <time.h>
     4 
     5 int main()
     6 {
     7    struct tm t;
     8 
     9    t.tm_sec    = 10;
    10    t.tm_min    = 10;
    11    t.tm_hour   = 6;
    12    t.tm_mday   = 25;
    13    t.tm_mon    = 2;
    14    t.tm_year   = 89;
    15    t.tm_wday   = 6;
    16 
    17    puts(asctime(&t));
    18    
    19    return(0);
    20 }

    运行结果:

    Sat Mar 25 06:10:10 1989

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

    C语言为了格式化输出时间信息又提供了强大的格式化函数strftime(),支持按自定义的格式打印出完整可阅读的时间信息,包括月份的全称或简称,或只选择某些关键时间值进行输出。
    参数s指向格式化后的时间字符串。
    参数max表示时间字符串的最大字符数(含字符串终止符)。
    参数format表示时间字符串的格式化表达式。
    参数tm表示待格式化的时间详情。

    其中format表达式支持格式化参数与字符混合使用,且所支持的格式化参数非常多,具体如下:

    说明符替换为实例
    %a 缩写的星期几名称 Sun
    %A 完整的星期几名称 Sunday
    %b 缩写的月份名称 Mar
    %B 完整的月份名称 March
    %c 日期和时间表示法 Sun Aug 19 02:56:02 2012
    %d 一月中的第几天(01-31) 19
    %H 24 小时格式的小时(00-23) 14
    %I 12 小时格式的小时(01-12) 05
    %j 一年中的第几天(001-366) 231
    %m 十进制数表示的月份(01-12) 08
    %M 分(00-59) 55
    %p AM 或 PM 名称 PM
    %S 秒(00-61) 02
    %U 一年中的第几周,以第一个星期日作为第一周的第一天(00-53) 33
    %w 十进制数表示的星期几,星期日表示为 0(0-6) 4
    %W 一年中的第几周,以第一个星期一作为第一周的第一天(00-53) 34
    %x 日期表示法 08/19/12
    %X 时间表示法 02:50:06
    %y 年份,最后两个数字(00-99) 01
    %Y 年份 2012
    %Z 时区的名称或缩写 CDT
    %% 一个 % 符号 %

    综合例子:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <time.h>
     4 int main (int argc, char ** argv) {
     5     time_t calendar_time = time(NULL);
     6     printf("calendar_time :%ld 
    ", calendar_time);
     7     
     8     char * calendar_str = ctime(&calendar_time);
     9     printf("calendar_str  :%s 
    ", calendar_str);
    10     
    11     struct tm * tm_local = localtime(&calendar_time);
    12     printf("localtime :year=%d mon=%d mday=%d hour=%d min=%d sec=%d   wday=%d yday=%d isdst=%d 
    ",
    13            tm_local->tm_year + 1900, tm_local->tm_mon + 1, tm_local->tm_mday, tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec,
    14            tm_local->tm_wday, tm_local->tm_yday, tm_local->tm_isdst);
    15     
    16     char * asc_time = asctime(tm_local);
    17     printf("asc_time  :%s", asc_time);
    18     char * c_time = ctime(&calendar_time);
    19     printf("c_time    :%s", c_time);
    20     
    21     time_t mk_time = mktime(tm_local);
    22     printf("
    mk_time   :%ld 
    
    ", mk_time);
    23     
    24     
    25     char str_f_t [100];
    26     strftime(str_f_t, sizeof(str_f_t), "%G-%m-%d %H:%M:%S", tm_local);
    27     printf("local  :format=%s 
    ", str_f_t);
    28     struct tm * gm_time = gmtime(&calendar_time);
    29     strftime(str_f_t, sizeof(str_f_t), "%G-%m-%d %H:%M:%S", gm_time);
    30     printf("gmtime :format=%s 
    
    ", str_f_t);
    31     
    32     struct tm my_tm = {2,2,2,16,2,2015,0,0,0};
    33     time_t my_time_t = mktime(&my_tm);
    34     printf("my yday:%d 
    ", my_tm.tm_yday);
    35     
    36     return 0;
    37 }

    运行结果:

    calendar_time :1512916710 
    calendar_str  :Sun Dec 10 22:38:30 2017
     
    localtime :year=2017 mon=12 mday=10 hour=22 min=38 sec=30   wday=0 yday=343 isdst=0 
    asc_time  :Sun Dec 10 22:38:30 2017
    c_time    :Sun Dec 10 22:38:30 2017
    
    mk_time   :1512916710 
    
    local  :format=2017-12-10 22:38:30 
    gmtime :format=2017-12-10 14:38:30 
    
    my yday:74 

    difftime

    double difftime(time_t time1, time_t time2);

    返回 time1 和 time2 之间相差的秒数 (time1 - time2)。这两个时间是在日历时间中指定的,表示了自纪元 Epoch(协调世界时 UTC:1970-01-01 00:00:00)起经过的时间。

     1 #include <stdio.h>
     2 #include <time.h>
     3 #ifdef _WIN32
     4 #include <Windows.h>
     5 #else
     6 #include <unistd.h>
     7 #endif
     8  
     9 int main ()
    10 {
    11    time_t start_t, end_t;
    12    double diff_t;
    13  
    14    printf("程序启动...
    ");
    15    time(&start_t);
    16  
    17    printf("休眠 5 秒...
    ");
    18    sleep(5);
    19  
    20    time(&end_t);
    21    diff_t = difftime(end_t, start_t);
    22  
    23    printf("执行时间 = %f
    ", diff_t);
    24    printf("程序退出...
    ");
    25  
    26    return(0);
    27 }

    运行结果:

    程序启动...
    休眠 5 秒...
    执行时间 = 5.000000
    程序退出...

    clock

    clock_t clock(void);

    返回程序执行起(一般为程序的开头),处理器时钟所使用的时间。为了获取 CPU 所使用的秒数,需要除以 CLOCKS_PER_SEC。在 32 位系统中,CLOCKS_PER_SEC 等于 1000000,该函数大约每 72 分钟会返回相同的值。本方法有一定缺陷,在32bit机器上,运行时间较长达到(超过1小时),有可能出现计时错误。
    clock()文档说明如下:
    Note that the time can wrap around. On a 32-bit system where CLOCKS_PER_SEC equals 1000000 this function will return the same value approximately every 72 minutes.
    因此,当出现计时为负数或者很小的数时,需要人为凭经验加上若干个72minutes……

    所以这个函数还是不要用了!

    例子:

     1 #include <time.h>
     2 #include <stdio.h>
     3  
     4 int main()
     5 {
     6    clock_t start_t, end_t;
     7    double total_t;
     8    int i;
     9  
    10    start_t = clock();
    11    printf("程序启动,start_t = %ld
    ", start_t);
    12     
    13    printf("开始一个大循环,start_t = %ld
    ", start_t);
    14    for(i=0; i< 10000000; i++)
    15    {
    16    }
    17    end_t = clock();
    18    printf("大循环结束,end_t = %ld
    ", end_t);
    19    
    20    printf("CLOCKS_PER_SEC = %ld
    ", CLOCKS_PER_SEC);
    21    total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
    22    printf("CPU 占用的总时间:%f
    ", total_t  );
    23    printf("程序退出...
    ");
    24  
    25    return(0);
    26 }

    运行结果:

    程序启动,start_t = 549
    开始一个大循环,start_t = 549
    大循环结束,end_t = 25777
    CLOCKS_PER_SEC = 1000000
    CPU 占用的总时间:0.025228
    程序退出...

    本文参考自:

    http://sodino.com/2015/03/15/c-time/

    http://www.runoob.com/cprogramming/c-standard-library-time-h.html

  • 相关阅读:
    lombok注解详细介绍
    基于注解的SpringMVC大致开发流程
    Thymeleaf知识点总结
    thymeleaf相关知识
    Windows 命令行查看占用端口,并关闭操作
    身份证号码的正则表达式及验证详解
    mysql的查询过程和SQL语句优化
    MySQL数据库知识点整理
    MySQL数据库
    MySQL数据库
  • 原文地址:https://www.cnblogs.com/abc-begin/p/8018597.html
Copyright © 2020-2023  润新知