专栏首页编程修养C 程序关于时间和日期的操作详解

C 程序关于时间和日期的操作详解

在平时的 C 语言编程中,经常会遇到关于时间和日期的相关操作。时间日期的操作其实并不难也不复杂,但是作为程序员还是必须要熟练掌握相关操作的,就像对待字符串和内存操作一样。

1. time_t 类型时间

在 C 语言中可以用 time_t 类型表示时间,time_t 类型时间其实就是所谓的「日历时间」,在 Linux 系统中就是距离 1970-01-01 08:00:00 这个时间点所经过的秒数,通常 time_t 是一个和 long 一样长的整数,但它似乎无法表示 1970 年以前的时间。

与 time_t 相关的最常用函数是 time_t time(time_t *t),它的参数是一个 time_t 类型的指针,返回一个与传入参数相等的 time_t 类型值,如果 time() 参数是 NULL,则返回当前时间。

time_t tt = time(NULL)

2. struct tm 类型时间

现在我们已经可以用 C 语言表示时间了,但是这个时间是距离 1970 年的秒数,只是个相对时间,通常我们需要得到更为详细的时间,这就要用到 struct tm 类型了,它可以表示更具体的时间信息。

struct tm {
    int tm_sec;  
    int tm_min;  
    int tm_hour; 
    int tm_mday; 
    int tm_mon;  
    int tm_year; 
    int tm_wday; 
    int tm_yday; 
    int tm_isdst;
};

struct tm 是一个结构体,我们需要先弄清楚它的具体成员信息,一个 struct tm 类型包括以下成员:

  • tm_year:表示年份,它是从 1900 年开始算的,所以程序中需要将 tm_year + 1900。
  • tm_mon:表示月份,它的值范围是 0 到 11,0 表示 1 月份,所以程序中需要将 tm_mon + 1。
  • tm_mday:表示当月的几号。
  • tm_hour:表示小时。
  • tm_min:表示分钟。
  • tm_sec:表示秒。
  • tm_wday:表示星期几,它的值范围是 0-6,0 是星期天,1 是星期一,6 是星期六。
  • tm_yday:表示当年的第几天,要注意的是 1 月 1 日是第 0 天。
  • tm_isdst:表示是否是夏令时。

与 struct tm 类型相关的函数是 localtime(),它可以把一个 time_t 类型构造成 struct tm 类型,具体来看下面的代码:

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

int main(int argc, char *argv[])
{
    time_t tt = time(NULL);
    struct tm *tm = localtime(&tt);
    printf("%d-%02d-%02d %02d:%02d:%02d\n",
        tm->tm_year + 1900, tm->tm_mon + 1,
        tm->tm_mday, tm->tm_hour,
        tm->tm_min, tm->tm_sec);
}

[root@sina ~]$ gcc main.c -o main
[root@sina ~]$ ./main
2018-05-07 11:39:02

3. string 类型时间

那么如何把 struct tm 类型转换为 time_t 类型呢?就用 mktime() 函数,注意参数是指针类型。那么如何输出时间呢?可以简单的使用 ctime() 函数和 asctime() 函数,需要注意的是返回字符串结尾包含换行符 \n。

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

int main(int argc, char *argv[])
{
    struct tm st;
    st.tm_year = 2018 - 1900;
    st.tm_mon = 4;
    st.tm_mday = 13;
    st.tm_hour = 10;
    st.tm_min = 47;
    st.tm_sec = 33;
    st.tm_isdst = 0;
    time_t tt = mktime(&st);
    printf("%s", asctime(&st));
    printf("%s", ctime(&tt));
}

[root@sina ~]$ gcc main.c -o main
[root@sina ~]$ ./main
Sun May 13 10:47:33 2018
Sun May 13 10:47:33 2018

我们自己用 struct tm 构造了一个时间,并且在执行 mktime() 函数后,tm_wday 属性也会自动计算出来。asctime() 函数是把 struct tm 格式转换为字符串格式,而 ctime() 是将秒数转换为字符串格式。

4. 高精度时间函数

C 语言中也可以使用函数 gettimeofday() 来获得时间,它的精度可以达到微秒,而且可以获取当地时区的信息。具体的函数原型及涉及的结构体如下:

#include <sys/time.h>
int gettimeofday(struct timeval *tv, \
                 struct timezone *tz);

// 时间相关结构
struct timeval {
    time_t      tv_sec;
    suseconds_t tv_usec;
};

// 时区相关结构
struct timezone {
    int tz_minuteswest;
    int tz_dsttime;
};

gettimeofday 可以获取到微秒级的时间,它有一个典型的应用场景,来计算测试某代码片段花费的时间,可以精确到微秒。

struct timeval tv1;
struct timeval tv2;

gettimeofday(&tv1, NULL);
... ... // 代码片段
gettimeofday(&tv2, NULL);
ret = tv2 - tv1 // 伪代码

5. clock 计算程序运行时间

在 time.h 中,clock() 函数返回程序运行到这条语句所消耗的时间,单位可以通过 CLOCKS_PER_SEC 来确认,我这里测试输出是 1000000,则证明是微秒。和 gettimeofday 一样,我们可以方便的用它来计算程序某一段语句所消耗的时间。

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

int main()
{
    int i = 0;
    printf("CLOCKS_PER_SEC: %ld\n", \
             CLOCKS_PER_SEC);
    long c = clock();
    while(i < 1<<30) i++;
    printf("The while cost %ld.\n", \
            clock() - c);
    c = clock();
    for(i = 0; i < 1<<30; i++);
    printf("The for cost %ld.\n", \
            clock() - c);
}

[root@sina ~]$ gcc main.c -omain
[root@sina ~]$ ./main
CLOCKS_PER_SEC: 1000000
The while loop cost 2950000.
The for loop cost 2970000.

clock_t 类型时间我们称为时钟计时单元,一个时钟计时单元的时间长短是由 CPU 控制的,一个 clock tick 不是 CPU 的一个时钟周期,而是 C/C++ 的一个基本计时单位。

7. 系统时间与硬件时间

顺道说下系统时间与 CMOS 时间的关系,系统时间是由操作系统来维护的,CMOS 时间是 CMOS 芯片保存的时间。系统启动时,操作系统将 CMOS 读出时间记录为系统时间,同时操作系统也会自动每隔一段时间将系统时间写入 CMOS 中。如果使用 date 命令修改系统时间后马上重启电脑,操作系统还没有来得及将系统时间同步到 CMOS,这样开机后还是没有修改的时间,所以推荐手动使用命令 clock 将系统时间同步到 CMOS 中。

$ date -s "2018-05-13 12:15:01"
$ clock -w

8. 最后总结

其实 C 语言给我们提供了很多个关于时间操作的函数,文中记录了一些比较常用的函数用法,掌握了这些函数的用法后基本上可以应付大部分程序中关于时间的操作。内容还是比较多的,这里再次简单总结下几类函数使用:

  • time_t 类型时间:从 1970 年距离当前时间的秒数,相关函数 time() mktime() gettimeofday()
  • struct tm 类型时间:具体的时间函数,localtime() mktime()
  • string 类型时间:输出为字符串格式的时间日期,ctime() asctime()
  • format string 类型时间:格式化的字符串格式时间日期,strftime() 文中没有具体讲解
  • clock tick 类型时间:计算程序运行的时间,精度为微秒,clock()

本文分享自微信公众号 - 编程修养(chopin11vip),作者:「肖邦」

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux 常用命令(三)

    curl 命令支持在线下载功能,使用方便,它支持,S,等协议,还支持PUT,POST,COOKIES,认证授权等操作。

    小徐
  • C语言知识汇总,史上最全面总结,没有之一

    C语言中文社区
  • .NET平台系列22:.NET Core/.NET5/.NET6 对比 .NET Framework

      在我的博客《.NET平台系列2 .NET Framework 框架详解》与 《.NET平台系列7 .NET Core 体系结构详解》 两篇文章中分别详细介绍...

    张传宁IT讲堂
  • 放弃 Calender优雅地使用Joda-Time吧Joda 大型项目Joda 简介Joda 和 JDK 互操作性Joda 的关键日期/时间概念

    JavaEdge
  • 运用AOP思想更优雅地进行性能调优

    在软件测试中,如果想在一个耗时严重的操作中找出其耗时的瓶颈时,一般采用的方法是在每个被调用的函数中写进测试代码,在运行时打出日志。如果该操作涉及到的业务逻辑特别...

    腾讯移动品质中心TMQ
  • 97 条 Linux 运维工程师常用命令总结

    作者:jeanheo 1.ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件 -A 通-a,但不列出...

    小小科
  • 收藏 | 97条 Linux 常用命令总结

    3.cp [选项] 源文件或目录 目录或多个源文件 | 将源文件复制至目标文件,或将多个源文件复制至目标目录。

    昱良
  • 97 条 Linux 运维工程师常用命令总结 | 史上最全Linux命令总结

    先说明一下,这篇文章只是一篇常用基础命令的汇总,小白可以看着学习一下,对大牛帮助不大。。。。

    谭庆波
  • 【经典收藏】掌握这些命令,玩转Linux小黑框!!

    来源:http://blog.csdn.net/qwe6112071/article/details/50806734

    Rookie
  • PHP中的日期相关函数(三)

    之前我们已经介绍过了 PHP 的一些相关的日期操作对象,今天我们就来学习剩下的那些面向过程的使用方式。当然,如果是和 DateTime 类中相似的方法我们就不再...

    硬核项目经理
  • 最基本的调试是NSLog及DEBUG预处理器宏

    在系统控制台显示日志信息运行应用程序时是最早调试机制之一,利用log你可以查看应用程序的运行记录,当程序运行完毕,你可以长时间查看。此外,您的应用程序运行期间,...

    君赏
  • 新病毒利用多家知名下载站疯狂传播 日感染量最高达十余万

    近日,火绒安全团队发现,新型病毒“VanFraud”正通过国内多家知名下载站的“高速下载器”大肆传播,日感染量最高可达10余万台。该病毒感染用户电脑后,会强行添...

    用户6477171
  • 在VC6.0中连接mysql数据库的方法实例

    (本文年代久远,请谨慎阅读)最近用JAVA写程序,在连接数据库并操作上感觉还是较其他语言简单多了,在这方面C/C++就显得有点繁杂,不过也并非难事。 首先就是要...

    ZONGLYN
  • #7 Python代码调试

    Python已经学了这么久了,你现在已经长大了,该学会自己调试代码了!相信大家在编写程序过程中会遇到大量的错误信息,我也不例外的啦~遇到这些问题该怎么解决呢?使...

    py3study
  • 大数据初学 或Java工程师怎么转大数据?大数据基础技术学习路线图

    1.数据在体量方面很大,比如说文字,有各种各样的来源,有电子书|实体书|杂志|报刊等,它们的数据大吧。

    用户2292346
  • [953]mongo创建索引及索引相关方法

    索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

    周小董
  • C++ 获取当前系统时间

    time() 是系统C语言的标准接口,通过man time 或者man 2 time 可查看详细的使用方法。

    宇航
  • Java基础知识点面试手册(线程+JDK8)

    在单核 CPU 中,将 CPU 分为很小的时间片,在每一时刻只能有一个线程在执行,是一种微观上轮流占用 CPU 的机制。

    Java3y
  • 【专业技术】 Linux下如何学习c语言?

    引言   尽管 C 语言问世已近 30 年,但它的魅力仍未减退。C 语言继续吸引着众多的开发者,他们为了编写、移植或维护应用程序而必须学习新技能。   本文是为...

    程序员互动联盟

扫码关注云+社区

领取腾讯云代金券