Linux学习笔记八:时间和延时gmtime和local函数返回相同
Posted 何事误红尘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux学习笔记八:时间和延时gmtime和local函数返回相同相关的知识,希望对你有一定的参考价值。
1. 概述
前面安装了开发环境,现在开始记录系统编程的笔记。打算按照自己的思路进行,先从最简单的开始,从最快上手做出东西的角度来学习。
2. 延时函数
在单片机编程时,使用软件延时常通过while循环来实现。而Linux系统编程则不再需要自己实现,延时函数有两个:sleep和usleep,前者是秒级,后者是微秒级。函数原型为:
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
简单测试下延时效果,可以这样:
while(i--) {
sleep(2);
printf("sleep 2\\n");
usleep(1000000);
printf("usleep 1000000\\n");
}
可以在终端看到sleep 2和usleep 1000000交替打印:
但是我们并不知道时间是否准确,因此再增加系统时间的获取。
3. 当前时间
时间获取分为两步:调用和转换。
3.1 时间调用函数
通过时间调用函数time
可以取得当前系统时间,其函数原型为:
#include <time.h>
time_t time(time_t *t)
得到的time_t类型时间值,实际是一个long型。它是一个机器日历时间,对于Linux来说也就是UNIX 纪元时间。
Unix time 是指从 1970 年 1 月 1 日 00:00:00 UTC 开始所经过的秒数。
根据传入参数是否为NULL,这个函数有两种使用方式:
time_t tiemp;
time(&timep);
timep = time(NULL);
在上面延时函数的基础上略作修改,以查看time
函数的作用:
while(i--) {
sleep(2);
time(&timep);
printf("sleep 2:UTC time: 0x08x\\n", timep);
usleep(1000000);
timep = time(NULL);
printf("usleep 1000000:UTC time: 0x08x\\n", timep);
}
运行结果如下:
可以看到:经过2秒延时,原本的unix时间0x60c80766
增加2变为0x60c80768
;再经过1000000微妙,也就是1秒延时,Unix时间又增加1变为0x60c80769
。与预期完全相符。
这个unix时间一大长串数字,显然还需要转换为直观易懂的时间格式,比如我们常说的某年某月的某一天。
3.2 时间转换函数
时间转换函数有四个:
char *ctime(const time_t *timep); //将时间转化为字符串格式。
struct tm *gmtime(const time_t *timep); //将时间转化为格林威治时间
struct tm *localtime(const time_t *clock); //将时间转化为本地时间。
char *asctime(const struct tm *tm); //将时间转换为字符格式
其中,前三个函数是直接对3.1节获取到的时间进行处理,而后面三个函数都涉及一个tm
结构体,结构体内包含了我们惯用的年月日时分秒:
struct tm{
int tm_sec; //秒 – 取值区间为[0,59]。
int tm_min; //分 - 取值区间为[0,59]。
int tm_hour; //时 - 取值区间为[0,23]。
int tm_mday;//一个月中的日期 - 取值区间为[1,31]。
int tm_mon;//月份(从一月开始,0 代表一月) - 取值区间为[0,11]。
int tm_year;//年份,其值等于实际年份减去 1900。
int tm_wday;//星期 – 取值区间为[0,6],其中 0 代表星期天,1 代表星期一,以此类推 。
int tm_yday;//从每年的 1 月 1 日开始的天数 – 取值区间为[0,365],其中 0 代表 1 月 1 日,1 代表 1 月 2 日,以此类推。
int tm_isdst; //夏令时标识符,实行夏令时的时候,tm_isdst 为正。不实行夏令时的进候,tm_isdst 为 0;不了解情况时,tm_isdst()为负。
对3.1小节代码进行修改:
while(i--) {
sleep(2);
time(&timep);
printf("sleep 2--UTC time: 0x%08x\\n", timep);
printf("sleep 2--ctime is %s", ctime(&timep)); //字符串输出
t_GTM = gmtime(&timep);
t_local = localtime(&timep);
printf("sleep 2--GTMtime is %s", asctime(t_GTM));
printf("sleep 2--localtime is %s", asctime(t_local));
printf("sleep 2--GTMtime current hour is %d\\n", t_GTM->tm_hour); //整型输出
printf("sleep 2--localtime current hour is %d\\n", t_local->tm_hour);
usleep(1000000);
timep = time(NULL);
printf("usleep 1000000--UTC time: 0x%08x\\n", timep);
printf("usleep 1000000--ctime is %s", ctime(&timep)); //字符串输出
t_GTM = gmtime(&timep);
t_local = localtime(&timep);
printf("usleep 1000000--GTMtime is %s", asctime(t_GTM));
printf("usleep 1000000--localtime is %s", asctime(t_local));
printf("usleep 1000000--GTMtime current hour is %d\\n", t_GTM->tm_hour); //整型输出
printf("usleep 1000000--localtime current hour is %d\\n", t_local->tm_hour);
}
查看打印结果:
这里格林威治时间和本地时间一样呢?
4. gmtime和local函数返回相同
查了一圈,原来是因为连续调用gmtime
和local
函数,导致后面的调用覆盖了前面的结果。调整下打印顺序:
t_GTM = gmtime(&timep);
printf("sleep 2--GTMtime is %s", asctime(t_GTM));
t_local = localtime(&timep);
printf("sleep 2--localtime is %s", asctime(t_local));
再次查看输出结果:
可以看到,调用local
之前,是正常的格林威治时间。调用local
之后,被覆盖为当地时间。
需要将调用之间的值复制到 gmtime 和 localtime :
返回值指向静态分配的结构,该结构可能会被随后对任何日期和时间函数的调用所覆盖。
这是常见的行为,至少在Linux上是如此。
(为什么localtime()和gmtime在c中给出相同的结果?)
在链接的帖子中有人提到,可以使用memcpy,也就是连续调用之间,将返回值拷贝走。对应修改下程序:
printf("sleep 2--ctime is %s", ctime(&timep)); //字符串输出
//t_GTM = gmtime(&timep);
t_GTM = (struct tm*)malloc(sizeof(struct tm));
memcpy(t_GTM, gmtime(&timep), sizeof(struct tm));
t_local = localtime(&timep);
只修改2S延时后的处理,1000000微妙的延时不做修改。再次看下输出:
这种方式确实有效,只是最后别忘了free
掉动态分配的内存。
测试代码
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int main()
{
unsigned char i = 1;
time_t timep;
struct tm *t_GTM = NULL;
struct tm *t_local = NULL;
while(i--) {
sleep(2);
time(&timep);
printf("sleep 2--UTC time: 0x%08x\\n", timep);
printf("sleep 2--ctime is %s", ctime(&timep)); //字符串输出
//t_GTM = gmtime(&timep);
t_GTM = (struct tm*)malloc(sizeof(struct tm));
memcpy(t_GTM, gmtime(&timep), sizeof(struct tm));
t_local = localtime(&timep);
printf("sleep 2--GTMtime is %s", asctime(t_GTM));
printf("sleep 2--localtime is %s", asctime(t_local));
printf("sleep 2--GTMtime current hour is %d\\n", t_GTM->tm_hour); //整型输出
printf("sleep 2--localtime current hour is %d\\n", t_local->tm_hour);
usleep(1000000);
timep = time(NULL);
printf("usleep 1000000--UTC time: 0x%08x\\n", timep);
printf("usleep 1000000--ctime is %s", ctime(&timep)); //字符串输出
t_GTM = gmtime(&timep);
t_local = localtime(&timep);
printf("usleep 1000000--GTMtime is %s", asctime(t_GTM));
printf("usleep 1000000--localtime is %s", asctime(t_local));
printf("usleep 1000000--GTMtime current hour is %d\\n", t_GTM->tm_hour); //整型输出
printf("usleep 1000000--localtime current hour is %d\\n", t_local->tm_hour);
free(t_GTM);
}
}
以上是关于Linux学习笔记八:时间和延时gmtime和local函数返回相同的主要内容,如果未能解决你的问题,请参考以下文章