timeval及相关函数

1.结构体定义

timeval结构体在头文件为sys/time.h中,定义如下:

struct timeval 
{
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

  该结构体以1970-01-01 00:00:00 +0000 (UTC),也就是Unix中的Epoch作为0,之后的时间都是相对于Epoch流逝的秒和毫秒数。其中tv_sec是秒,tv_usec微秒(microsecond ),即10-6秒,而不是毫秒(millisecond),10-3秒。

 

2. 关联函数

gettimeofday

位于头文件sys/time.h中,函数声明如下:

int gettimeofday(struct timeval *tv, struct timezone *tz);

  用于获取调用该代码时,距离Epoch的时间。

第一个参数不用多说,第二个参数也是结构体,定义如下:

struct timezone 
{
    int tz_minuteswest;     /* minutes west of Greenwich */
    int tz_dsttime;         /* type of DST correction */
};

 根据Linux的手册中关于函数gettimeofday的描述(man gettimeofday):

The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL

这种使用方式是过时的,该处通常提供NULL作为参数。

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

int main()
{
    struct timeval tv;int i;
    
    for(i=0;i<5;i++)
    {
        gettimeofday(&tv, NULL);
        printf("%ld.%06ld\n", tv.tv_sec, tv.tv_usec);
        sleep(1);    
    }
    return 0;
}

运行效果如下(和运行时间有关):

1610953256.769513
1610953257.769901
1610953258.770804
1610953259.771444
1610953260.771719

可以看到,并不是非常精确的1秒延时,多次测试发现延时都会滞后一点不过在一般的应用场合是足够了,例如,我们可以两次调用这个函数,测试一段代码执行所消耗的时间等。

另外一个与之相关的函数是settimeofday,看名字就知道是和gettimeofday对应的,这里就不去展开讨论了。

3. 同日期之间的转换

在获取了相对于Epoch的时间以后,相应的日期也就可以确定了,这个时候就要用到time.h中的结构体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 */ };

与之相关的几个函数分别是gmtime\localtime、mktime。

先说说将时间戳转换为日期的函数gmtime和localtime,前者是GMT时间,而后者是本地时间,例如现在北京时间是下午16点,则GMT时间实际上是当日的上午8点(我们在东八区,记作GMT+8)。

gmtime定义如下:

struct tm *gmtime(const time_t *timep);

接收一个time_t*的指针,然后将其转换为了代表gmt时间的结构体t指针,需要年月日时分秒等,都可以从这个返回的tm结构体中获取,测试代码如下。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

int main()
{
    struct timeval tv;    
    struct tm* st;
    gettimeofday(&tv, NULL);    
    printf("%ld.%06ld\n", tv.tv_sec, tv.tv_usec);
    st=gmtime(&tv.tv_sec);
    printf("%02d:%02d:%02d\n",st->tm_hour,st->tm_min,st->tm_sec);
    return 0;
}

这将显示当前的时间,由于使用的是GMT时间,因此,比北京时间慢了8小时,如果使用localtime而不是gmtime的话,则和北京时间相同。

反过来,如果我们向知道某个日期所对应的相对Epoch时间是多少,则可以使用mktime函数,这个函数原型如下:

time_t mktime(struct tm *tm);

就是将tm结构体指针转换为time_t,测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

int main()
{
    time_t tt;
    struct tm st;
    st.tm_year=121;//year=1900+121=2021
    st.tm_mon=0;//for Jaunary
    st.tm_mday=18;
    st.tm_hour=7;
    st.tm_min=39;
    st.tm_sec=34;
    tt=mktime(&st);
    printf("%ld\n",tt);
    return 0;
}

 

posted @ 2021-01-18 15:41  castor_xu  阅读(18640)  评论(0编辑  收藏  举报