结构体tm的定义如下:

struct tm{int tm_sec;/* Seconds.[0-60] (1 leap second) */int tm_min;/* Minutes.[0-59] */int tm_hour;/* Hours.[0-23] */int tm_mday;/* Day.[1-31] */int tm_mon;/* Month.[0-11] */int tm_year;/* Year- 1900. */int tm_wday;/* Day of week.[0-6] */int tm_yday;/* Days in year.[0-365]*/int tm_isdst;/* DST.[-1/0/1]*/#ifdef__USE_BSDlong int tm_gmtoff;/* Seconds east of UTC. */__const char *tm_zone;/* Timezone abbreviation. */#elselong int __tm_gmtoff;/* Seconds east of UTC. */__const char *__tm_zone;/* Timezone abbreviation. */#endif};

使用它需要包含Linux的默认头文件存储路径/usr/include中的头文件time.h,但是它只能精确到秒。

系统还为我们定义了另一些和时间相关的头文件,在一个叫sys的子目录中。该目录的位置和系统有一定关系。比如我用的Ubuntu 20.04.4 LTS,该子目录位置:/usr/include/x86_64-linux-gnu/sys。在这个目录中的头文件timeb.h中定义了结构体timeb:

struct timeb{    time_t time;                /* Seconds since epoch, as from `time'.  */    unsigned short int millitm;    /* Additional milliseconds.  */    short int timezone;         /* Minutes west of GMT.  */    short int dstflag;          /* Nonzero if Daylight Savings Time used.  */};

其中的成员变量time为从Epoch到创建struct timeb时经历的秒数,millitm为附加的毫秒数。利用这个结构体,就可以获取到精确到毫秒的时间了。

头文件timeb.h中还声明了函数ftime:

extern int ftime (struct timeb *__timebuf) __nonnull ((1)) __attribute_deprecated__;

此函数的参数是结构体timeb的指针,调用此函数就会将获取到的时间,包含秒数和毫秒数放到参数变量中。

然后需要将获取到的秒数转成时间格式,需要调用函数localtime。此函数在头文件time.h中声明:

/* Return the `struct tm' representationof *TIMER in the local timezone.  */extern struct tm *localtime (const time_t *__timer) __THROW;

因此,我们需要将获取到的秒数的指针传给localtime(),该函数返回指向结构体tm的指针。将结构体tm的成员变量按照格式输出就可以了。

代码如下:

#include #include #include int main(void){    struct timeb tTimeB;    ftime(&tTimeB);//获取当前的秒数和毫秒数    struct tm *tTM = localtime(&tTimeB.time);//将秒数转为时间格式    printf("%04d-%02d-%02d %02d:%02d:%02d.%03d\n", tTM->tm_year + 1900,     tTM->tm_mon + 1, tTM->tm_mday, tTM->tm_hour, tTM->tm_min, tTM->tm_sec,     tTimeB.millitm);    return 0;}

编译会有警告,ftime函数不推荐使用,不过并不影响编译和运行:

如果要进一步精确到微秒需要使用结构体timeval,使用它需要包含头文件sys/time.h:

struct timeval{__time_t  tv_sec;        /* Seconds. */__suseconds_t  tv_usec;  /* Microseconds. */};

成员变量tv_sec是从Epoch到创建struct timeval时经历的秒数,tv_usec是额外的微秒数。

获取当前时间(秒数和微秒数)需要调用函数gettimeofday,该函数也是在sys/time.h中声明:

/* Get the current time of day, putting it into *TV.   If TZ is not null, *TZ must be a struct timezone, and both fields   will be set to zero.   Calling this function with a non-null TZ is obsolete;   use localtime etc. instead.   This function itself is semi-obsolete;   most callers should use time or clock_gettime instead. */extern int gettimeofday (struct timeval *__restrict __tv,                         void *__restrict __tz) __THROW __nonnull ((1));

此函数有两个参数,第一个是结构体timeval的指针,第二个参数表示时区,如果不需要获取可以传NULL。调用它之后就可以获取到当前时间的秒数和额外的微秒数。

然后同样调用localtime函数将秒数转成时间格式。我们想输出的格式是:年-月-日 时:分:秒.毫秒.微秒,因此将tv_usec / 1000就是毫秒值,将tv_usec %1000就是剩余的微秒值。代码如下:

#include #include #include int main(void){        struct timeval tTimeVal;        gettimeofday(&tTimeVal, NULL);        struct tm *tTM = localtime(&tTimeVal.tv_sec);        printf("%04d-%02d-%02d %02d:%02d:%02d.%03ld.%03ld\n",         tTM->tm_year + 1900, tTM->tm_mon + 1, tTM->tm_mday,         tTM->tm_hour, tTM->tm_min, tTM->tm_sec,                     tTimeVal.tv_usec / 1000, tTimeVal.tv_usec % 1000);        return 0;}

编译运行:

参考资料:

1、linux timeb 结构体,Linux time函数:https://blog.csdn.net/weixin_39867200/article/details/116927426

2、struct timeval结构体:https://blog.csdn.net/lizhengze1117/article/details/103313928