linux中标准接口函数——时间和日期

21. 时间和日期

谈到时间(包括日期),必须先明确下面的概念:

  1. 格林威治时间(Coordinated Universal Time).
  2. 世界标准时间(UTC).这里面需要知道下面一些概念:
    1. 时区(time zone):由于世界各国家与地区经度不同,地方时也有所不同,因此将其划分为24个时区,其中UTC(Coordinated Universal Time,世界标准时间)(以前称为格林威治时间(GMT))为0时区。
    2. 夏令时:现在用的不多了。建议百度下概念。
  3. 1970年1月1日-00.00.00(UTC):posix标准的固定时间点(epoch)。计算机使用整型数计秒的起始点。
  4. 分解时间(broken-down time):就是将时间按照年、月、日、时、分、秒等格式显示的时间。如Wed Apr 1 11:23:33 2020
    1. 注意:它与时区(time zone)相关。
  5. 简单日历时间(simple calendar time):就是从固定时间点(1970年1月1日-00.00.00(UTC))到当前时间点所经过的秒数。计算机在计时时就使用它。
    1. 注意:它与时区(time zone)无关。固定为0区(UTC).

其次,我们首先需要了解几个时间相关的数据类型和数据结构:

  1. clock_t数据类型:系统滴答计数。可用于测量进程和cpu的时间。
  2. time_t数据类型:代表从一个固定时间点到当前时间点所经过的秒数的数据类型。
  3. struct timespec数据类型:类似time_t。它包含更精确的时间ns。结构体成员如下
    struct timespec{
        time_t  tv_sec;         /* 秒, */
        long    tv_nsec;        /* 纳秒  */
        //eg:tv_sec + tv_nsec为从epoch开始到目前所经过的时间
    };
    
  4. struct tm:表示分解时间的数据类型,结构体成员如下
    struct tm {
        int tm_sec;    /* Seconds (0-60) */
        int tm_min;    /* Minutes (0-59) */
        int tm_hour;   /* Hours (0-23) */
        int tm_mday;   /* Day of the month (1-31) */
        int tm_mon;    /* Month (0-11) */
        int tm_year;   /* Year - 1900 */
        int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
        int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
        int tm_isdst;  /* Daylight saving time */
    };
    //tm_isdst:和夏令时有关。
    //gnu扩展了两个参数tm_gmtoff和tm_zone,是和时区相关的
    //其中tm_gmtoff指定了当前时间在日期变更线两边的秒数(东为正,西为负)
    //tm_zone为当前时区的字符串名称,如CST.
    

有了上面的基础。它的相关函数就很容易理解和使用了。因为计算机使用简单日历时间,而使用者一般使用分解时间.所以时间相关的函数很多都是关于它俩转换的。使用下面的函数都需要包含头文件time.h
大体分为下面几类:

  1. 获取、修改系统时间相关的函数。
  2. 通过简单日历时间来获取(或转换)为分解时间相关函数.
  3. 根据分解时间来获取(或转换)为简单日历时间相关函数。
  4. 简单日历时间转换为字符串相关函数。
  5. 分解时间转换为字符串相关函数。
  6. 将字符串转换为分解时间简单日历时间相关函数。
  7. 时区操作相关函数.
  8. 让系统睡眠相关的函数。

获取、修改系统时间相关的函数

  1. time_t time(time t *result)
    1. 描述:获取时间(秒数),这个秒数从1970-01-01 00:00:00 +0000 (UTC)计算。
    2. result:如果不为空,返回值同时保存在这个参数中。
    3. return:返回时间值。
  2. int clock_gettime(clockid t clock, struct timespec *ts)
    1. 描述:获取时间,精确到ns.
    2. clock:
      1. CLOCK_REALTIME:系统真实的时间.随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变.
      2. CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响.
      3. CLOCK_PROCESS_CPUTIME_ID:此进程总共占cpu的时间。
      4. CLOCK_THREAD_CPUTIME_ID:此进程总共占cpu的时间。
    3. ts:获取到的时间。
    4. return:成功为0,失败为-1.
  3. int clock_getres(clockid t clock, struct timespec *res)
    1. 描述:获取时间精度.
    2. clock:同上.
    3. res:获取到的时间精度。
  4. int gettimeofday (struct timeval *tp, void *tzp)
    1. 描述:获取时间,精确到ms.不建议使用,一般用clock_gettime()代替。
  5. int clock_settime(clockid t clock, const struct timespec *ts)
    1. 描述:修改当前时间。需要有相应的权限。这个函数不关心时区。对于在系统运行时所做的小更改,最好使用ntp_adjtime()来实现从一个时间到另一个时间的平稳过渡。
    2. 其他同上。

将日历时间转换为分解时间相关函数

  1. struct tm *localtime(const time_t *timep)
    1. 描述:将日历时间转换成系统当前时区的分解时间。由于它不是线程安全函数。所以建议使用它的代替品localtime_r()函数。
    2. timep:日历时间指针。一般通过time()函数获取。
    3. return:返回分解时间的结构体指针。
  2. struct tm *localtime_r(const time_t *timep, struct tm *result)
    1. 功能同localtime()函数,但它是线程安全的。
    2. result:用于保存转换后的分解函数数据。
  3. struct tm *gmtime(const time_t *timep)
    1. 描述:类似localtime(),它是将日历时间转换成时0区(即UTC时间)的分解时间。
  4. struct tm *gmtime_r(const time_t *timep, struct tm *result)
    1. 功能同gmtime()函数,但它是线程安全的。

将分解时间转换为日历时间相关函数

  1. time_t mktime(struct tm *tm)
    1. 描述:将分解时间转换成日历时间,同时填充tm对象中的某些成员。如tm_day,tm_yday,tm_isdst等。如果结构成员超出其有效区间,则将其规范化。如4月40号会被修改为4月9号。此函数使用的时区为系统默认时区。
    2. return:如果指定的tm不能转换成日历时间,返回-1.成功则返回日历时间.
  2. time_t timelocal(struct tm *tm)
    1. 描述:功能类似mktime().
  3. time_t timegm(struct tm *tm)
    1. 描述:功能类似mktime().但是它将输入值tm当作UTC时间。(不管tm中设置的时区是什么)。

将时间转换为字符串相关函数

  1. char *asctime(const struct tm *tm)
    1. 描述:将分解时间转换成字符串。如"Tue May 21 13:46:22 1991\n"。它不是线程安全的,建议使用asctime_r()代替。
    2. return:返回一个静态的字符串指针。
  2. char *asctime_r(const struct tm *brokentime, char *buffer)
    1. 描述:效果和asctime()一样。它是线程安全的。
    2. buffer:长度要至少大于26字节。
    3. return:返回buffer的指针。
  3. char *ctime(const time_t *time)
    1. 描述:将日历时间转换为分解时间。效果等同于asctime (localtime (time))它不是线程安全的,建议使用ctime_r()代替。
    2. return:返回一个静态的字符串指针。
  4. char *ctime_r(const time_t *time, char *buffer)
    1. 描述:ctime()一样。它是线程安全的。
    2. buffer:长度要至少大于26字节。
    3. return:返回buffer的指针。
  5. size_t strftime(char *s, size_t max, const char *format,const struct tm *tm)
    1. 描述:此函数类似sprintf().用户通过format参数自己指定转换格式,得到分解时间的字符串。
    2. format:可以指定的格式:
      1. %A:指定星期(全名)。
      2. %B:指定月份(全名)。
      3. %C:指定年(比如1970会显示70)。
      4. …具体查看man手册
    3. return:返回buffer的指针。
  6. char *strptime(const char *s, const char *format, struct tm *tm)
    1. 描述:将时间字符串转换成分解时间.
  7. struct tm *getdate(const char *string)
    1. 描述:将时间字符串转换成分解时间.线程不安全。建议使用getdate_r()代替。

操作时区相关的函数、变量

注意使用下面的全局变量前最好使用tzset()刷新一下。

  1. TZ
    1. 环境变量。与时域相关。
  2. char * tzname[2]
    1. 全局变量。包含两个变量。其中tzname[0]是一个指向一个标准时间域字符串。如EST.tzname[1]跟夏令时有关。
  3. long int timezone
    1. 全局变量。UTC时区与当地时区的差值。单位为秒。
  4. int daylight
    1. 全局变量。如果应用夏令时规则,此变量的值为非零。
  5. void tzset(void)
    1. TZ环境变量初始化tzname变量。用户一般无需调用此函数,因为在调用其他时间转换函数时被自动调用。

使用例程

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "signal.h"

void main(void)
{
    time_t curtime;
    char timeStrBuff[64];
    struct tm *ploctime,timeInfo;

    /* 获取当前时间(日历时间) */
    curtime = time(NULL);
    printf("calender time:%ld \n",curtime);

    /* 转换为分解时间 */
    ploctime = localtime_r(&curtime,&timeInfo);
    char *pTimeStr = asctime_r(ploctime,timeStrBuff);
    printf("%s",pTimeStr);

    /* 转换成自定义格式 */
    strftime (timeStrBuff, 64, "Today is %A, %B %d.\n", ploctime);
    printf("%s",timeStrBuff);
    strftime (timeStrBuff, 64, "The time is %I:%M %p.\n", ploctime);
    printf("%s",timeStrBuff);
}

关于技术交流

此处后的文字已经和题目内容无关,可以不看。
qq群:825695030
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。二维码

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theboynoName

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值