在linux下編程,有一些常用的時間函數,下面做一個總結梳理。
1、time
SYNOPSIS
#include <time.h>
time_t time(time_t *t);
DESCRIPTION
time() returns the time since the Epoch (00:00:00 UTC, January 1, 1970), mea-
sured in seconds.
If t is non-NULL, the return value is also stored in the memory pointed to by
t.
先說一下,time_t類型是一個有符號整數,是32位系統下,就是32位有符號數,在64位系統下,就是64位有符號數。那麼time函數返回的是自從UTC時間1970年1月1日 00:00:00到現在經過的秒數,如果32位有符號數存儲這個值,那麼在2038年這個值將溢出,無法存儲這麼大的數了。
這個函數傳進去一個time_t指針,會將時間寫入這個傳入的內存,同時time也返回這個值,總感覺有點多餘,要麼用返回值,要麼用指針。
int now = time(NULL); // 常用的形式
2、localtime
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
/*
The members of the tm structure are:
tm_sec The number of seconds after the minute, normally in the range 0 to
59, but can be up to 60 to allow for leap seconds.
tm_min The number of minutes after the hour, in the range 0 to 59.
tm_hour The number of hours past midnight, in the range 0 to 23.
tm_mday The day of the month, in the range 1 to 31.
tm_mon The number of months since January, in the range 0 to 11.
tm_year The number of years since 1900.
tm_wday The number of days since Sunday, in the range 0 to 6.
tm_yday The number of days since January 1, in the range 0 to 365.
tm_isdst A flag that indicates whether daylight saving time is in effect at
the time described. The value is positive if daylight saving time
is in effect, zero if it is not, and negative if the information is
not available.
*/
這兩個函數是將time_t的時間戳轉化爲本地且容易閱讀的時間,關鍵是tm結構體,註釋已經很清楚了。這兩個函數的區別是前者是線程不安全的函數,後者是線程函數函數。你看第一個函數,平白無故的返回一個指針,很少看到這種情況,其實這個指針指向的是一個函數內部靜態分配的結構體,有可能被其他線程重寫,所以是不安全的,儘量用第二個。
3、gettimeofday
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of DST correction */
};
這個函數也可以得到當前的時間,而且可以達到微秒級別,由第一個參數tv指針傳出,第二個參數tz已經廢棄,傳入NULL即可。
timeval結構體,保存秒數和微秒數,也是從UTC時間1970年1月1日 00:00:00算起的。
測試程序:
#include <stdio.h>
#include <time.h>
#include<sys/time.h>
int main ()
{
struct timeval tv;
gettimeofday(&tv,NULL);
printf("second=%d\n", tv.tv_sec);
printf("microseconds=%d\n", tv.tv_usec);
printf("time=%d\n", time(0));
return 0;
}
輸出:
[KentZhang@LOCAL-192-168-97-2 ]$ ./a.out
second=1543334965
microseconds=963832
time=1543334965
4、clock_gettime
#include <time.h>
int clock_gettime(clockid_t clk_id, struct timespec *tp);
/*
clk_id 有以下五種取值,我只用過前2個,後面3個待研究。
CLOCK_REALTIME // 獲取實時時間,類似time()
System-wide real-time clock. Setting this clock requires appropriate
privileges.
CLOCK_MONOTONIC // 獲取系統從啓動到現在經歷的時間
Clock that cannot be set and represents monotonic time since some
unspecified starting point.
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-
based time that is not subject to NTP adjustments.
CLOCK_PROCESS_CPUTIME_ID
High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
Thread-specific CPU-time clock.
*/
// 傳出參數的結構體,保存秒和納秒
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
據說這個函數是獲取系統的時鐘時間,和CPU的時鐘有關係,所以精度才比較高。