linux/unix下常用時間函式
1.與時間有關的資料型別
常用的主要有time_t, struct timeb, struct timeval, struct timezone, struct timespec, clock_t,struct tm。
(1).time_t : 這個變數是一個long型,一般用來表示從1970-01-01 00:00:00時以來的秒數,精確度:秒;由函式time()獲取。定義在#include <time.h>
中。
目前相當一部分作業系統使用32位二進位制數字表示時間。此類系統的Unix時間戳最多可以使用到格林威治時間2038年01月19日03時14分07秒(二進位制:01111111 11111111 11111111 11111111)。其後一秒,二進位制數字會變為10000000 00000000 00000000 00000000,發生溢位錯誤,造成系統將時間誤解為1901年12月13日20時45分52秒。這很可能會引起軟體故障,甚至是系統癱瘓。使用64位二進位制數字表示時間的系統(最多可以使用到格林威治時間292,277,026,596年12月04日15時30分08秒)則基本不會遇到這類溢位問題。
(2).struct timeb 結構:它有兩個主要成員,一個是秒,另一個是毫秒;精確度:毫秒(10E-3秒)。
由函式ftime()獲取struct timeb結構的時間;其定義如下:
struct timeb{
time_t time; //秒
unsigned short millitm;//毫秒
short timezone; //Minutes west of GMT
short dstflag; // Nonzero if Daylight Savings Time used
};
#include <sys/timeb.h>
int ftime(struct timeb* tp);
呼叫成功返回0;呼叫失敗返回-1。
(3).struct timeval 結構,它有兩個成員;一個是秒,另一個表示微秒,精確度:微秒(10E-6)。
由函式gettime0fday()獲取;
struct timeval結構定義為:
struct timeval{
long tv_sec; //秒
long tv_usec; //微秒
};
讀取struct timeval結構資料的函式說明:
#include <sys/time.h>
int gettimeofday(struct timeval* tv,struct timezone* tz);
該函式會提取系統當前時間,並把時間分為秒和微秒兩部分填充到結構struct timeval中;
同時把當地的時區資訊填充到結構struct timezone中;
返回值:成功則返回0,失敗返回-1,錯誤程式碼存於errno。附加說明EFAULT指標tv和tz所指的記憶體空間超出存取許可權。
(4).struct timezone結構的定義為:
struct timezone{
int tz_minuteswest;
int tz_dsttime;
};
上述兩個結構都定義在/usr/include/sys/time.h。tz_dsttime 所代表的狀態如下:
DST_NONE
DST_USA
DST_AUST
DST_WET
DST_MET
DST_EET
DST_CAN
DST_GB
DST_RUM
DST_TUR
DST_AUSTALT
(5).struct timespec 結構:它是POSIX.4標準定義的一個時間結構,精確度:納秒(10E-9秒)。
由函式 clock_gettime 獲取當前系統struct timespec結構的時間;其定義如下:
struct timespec{
time_t tv_sec; //秒
long tv_nsec; //納秒
};
typedef struct timespec timespec_t;
該結構定義在頭標頭檔案 `/usr/include/time.h` 中;
int clock_gettime (clock_t which_clock, struct timespec *tp);
(6).clock_t 型別:由函式clock()獲取。
#include <time.h>
clock_t clock(void);
linux下該函式以微秒的方式返回CPU的時間;
typedef long clock_t;
(7).struct tm 結構:由函式gmtime()解析time_t得到。
struct tm*gmtime(const time_t*timep);
函式說明:gmtime()將引數timep 所指的time_t 結構中的資訊轉換成真實世界所使用的時間日期表示方法,然後
將結果由結構tm返回。
struct tm{
int tm_sec; // 代表目前秒數,正常範圍為0-59 ,但允許至61
int tm_min; // 代表目前分數,範圍為0-59
int tm_hour; // 從午夜算出的時數,範圍 0-23
int tm_mday; // 目前月份的日期,範圍為 1-31
int tm_mon; // 代表目前月份,從1月算起,範圍為 0-11
int tm_year; // 從1900年算起至今的年數
int tm_wday; // 一個星期的日數,從星期一算起,範圍為0-6
int tm_yday; // 從今年1月1日算起至今的天數,範圍為0-365
int tm_isdst; //日光節能時間的旗標
};
注意:#include <time.h>和#include <sys/time.h>
後者總包括了前者
2.常用的時間函式
Linux下常用時間函式有:clock()、time( )、ctime( )、gmtime( )、localtime( )、mktime( )、asctime( )、difftime( )、gettimeofday( )、settimeofday( )
(1).clock_t clock (void);
標頭檔案:#include <time.h>
函式說明:返回從“開啟這個程式程序”到“程式中呼叫clock()函式”時之間的CPU時鐘計時單元(clock tick)數
返 回 值:標準POSIX平臺下1000000個計時單位為1秒,所以返回的單位相當於us(微秒)
windows下1000個計時單元為1秒,返回的單位相當於ms(毫秒)
(2).time_t time(time_t * t);
標頭檔案:#include <time.h>
函式說明:返回從公元1970年1月1日的UTC時間從0時0分0秒算起到現在所經過的秒數。
如果t 並非空指標的話,此函式也會將返回值存到t指標所指的記憶體。time_t = time(0);或者time_t t;time(&t);
返 回 值:成功則返回秒數,失敗則返回((time_t)-1)值錯誤原因存於errno中。
(3).double difftime(time_t time1, time_t time0);
標頭檔案:#include <time.h>
函式說明:difftime( )比較引數timep1和timep2時間是否相同,並返回之間相差秒數。
返 回 值:返回相差秒數,注意返回型別為double,可正可負。
示例:
#include <stdio.h>
#include <time.h>
int main ()
{
time_t timer;
struct tm y2k;
double seconds;
y2k.tm_hour = 0; y2k.tm_min = 0; y2k.tm_sec = 0;
y2k.tm_year = 100; y2k.tm_mon = 0; y2k.tm_mday = 1;
time(&timer); /* get current time; same as: timer = time(NULL) */
seconds = difftime(timer,mktime(&y2k));
printf ("%.f seconds since January 1, 2000 in the current timezone", seconds);
return 0;
}
(4).time_t mktime(struct tm * timeptr);
標頭檔案:#include <time.h>
函式說明:mktime()用來將引數timeptr所指的tm結構資料轉換成從公元1970年1月1日0時0分0 秒算起至今的UTC時間所經過的秒數。
返 回 值:返回經過的秒數。
示例: 用time()取得時間(秒數),利用localtime()轉換成struct tm,再利用mktine()將struct tm轉換成原來的秒數
#include <stdio.h>
#include <time.h>
int main(){
time_t timep = time(0);
strcut tm *p;
printf("time() : %d \n",timep);
p=localtime(timep);
timep = mktime(p);
printf("time()->localtime()->mktime():%d\n",timep);
return 0;
}
執行結果:
time():974943297
time()->localtime()->mktime():974943297
(5).char * asctime(const struct tm * timeptr);
標頭檔案:#include <time.h>
函式說明:將引數timeptr所指的tm結構中的資訊轉換成真實世界所使用的時間日期表示方法,然後將結果以字串形態返回。此函式已經由時區轉換成當地時間,字串格式為:”Wed Jun 30 21:49:08 1993\n”
返 回 值:若再呼叫相關的時間日期函式,此字串可能會被破壞。此函式與ctime不同處在於傳入的引數是不同的結構。
附加說明:返回一字串表示目前當地的時間日期
示例:
#include <stdio.h>
#include <time.h>
int main(){
time _t timep=time(0);
printf("%s",asctime(gmtime(&timep)));
return 0;
}
執行結果:
Sat Oct 28 02:10:06 2015
(6).char * ctime(const time_t *timep);
標頭檔案:#include <time.h>
函式說明: 將時間和日期以字串格式表示
ctime ()將引數timep所指的time_t結構中的資訊轉換成真實世界所使用的時間日期表示方法,然後將結果以字串形態返回。此函式已經由時區轉換成當地 時間,字串格式為”Wed Jun 30 21 :49 :08 1993\n”。若再呼叫相關的時間日期函式,此字串可能會被破壞。
返 回 值:返回一字串表示目前當地的時間日期。
示例:
#include <stdio.h>
#include <time.h>
int main(){
time_t timep;
time(&timep);
printf("%s",ctime(&timep));
return 0;
}
執行結果:
Sat Oct 28 10:12:05 2015
(7).struct tm* gmtime (const time_t* timep);
標頭檔案:#include <time.h>
函式說明:gmtime()將引數timep 所指的time_t 結構中的資訊轉換成真實世界所使用的時間日期表示方法,
然後將結果由結構tm返回。
返 回 值:返回結構體tm,返回的日期未經時區轉換,而是UTC時間。
示例:
#include <stdio.h>
#include <time.h>
int main(){
char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
time_t timep;
struct tm *p;
time(timep);
p=gmtime(timep);
printf("%d/%d/%d",(1900+p->m_year), (1+p->tm_mon),p->tm_mday);
printf("%s%d:%d:%d\n", wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
return 0;
}
執行結果:
2015/10/28 Sat 8:15:38
(8).struct tm* localtime (const time_t* _v);
標頭檔案:#include <time.h>
函式說明:將引數timep所指的time_t結構中的資訊轉換成真實世界所使用的時間日期表示方法,然後將結果由結構tm返回。
和gmtime區別就是此函式返回的時間日期已經轉換成當地時區。
返 回 值:返回結構tm代表目前的當地時間,已轉換為當地時區。
(9).int gettimeofday(struct timeval*tv, struct timezone *tz);
標頭檔案:#include <sys/time.h>
函式說明:gettimeofday()會把目前的時間有tv所指的結構返回,timezone 引數若不使用則傳入NULL即可。
當地時區的資訊則放到timeval結構體中。
timeval結構體定義為:
struct timeval {
long tv_sec;//秒
long tv_usec;//微秒
};
timezone結構體定義為:
struct timezone{
int tz_minuteswest;/*和Greenwich時間差了多少分鐘*/
int tz_dsttime; /*日光節能時間的狀態*/
}
上述兩個結構都定義在/usr/include/sys/time.h
。tz_dsttime 所代表的狀態如下:
DST_NONE /*不使用*/
DST_USA /*美國*/
DST_AUST /*澳洲*/
DST_WET /*西歐*/
DST_MET /*中歐*/
DST_EET /*東歐*/
DST_CAN /*加拿大*/
DST_GB /*大不列顛*/
DST_RUM /*羅馬尼亞*/
DST_TUR /*土耳其*/
DST_AUSTALT /*澳洲(1986年以後)*/
返 回 值:成功則返回0,失敗返回-1,錯誤程式碼存於errno。附加說明EFAULT指標tv和tz所指的記憶體空間超出存取許可權。
它獲得的時間精確到微秒(1e-6 s)量級。
示例:
#include <stdio.h>
#include <sys/time.h>
int main(){
struct timeval tv;
struct timezone tz;
gettimeofday (tv , tz);
printf("tv_sec: %d\n", tv.tv_sec) ;
printf("tv_usec: %d\n",tv.tv_usec);
printf("tz_minuteswest: %d\n", tz.tz_minuteswest);
printf("tz_dsttime: %d\n",tz.tz_dsttime);
return 0;
}
執行結果:
tv_sec: 974857339
tv_usec:136996
tz_minuteswest:-540
tz_dsttime:0
(10). int settimeofday ( const struct timeval *tv,const struct timezone *tz);
標頭檔案:#include <sys/time.h>
函式說明:settimeofday()會把目前時間設成由tv所指的結構資訊,當地時區資訊則設成tz所指的結構。詳細的說明請參考gettimeofday()。注意,只有root許可權才能使用此函式修改時間。
返回值:成功則返回0,失敗返回-1,錯誤程式碼存於errno。
錯誤程式碼:
EPERM 並非由root許可權呼叫settimeofday(),許可權不夠。
EINVAL 時區或某個資料是不正確的,無法正確設定時間。
(11).時間格式化函式 strftime
函式:size_t strftime(char *str,size_t max,char *farmat,struct tm *timeptr);
標頭檔案:#include <time.h>
strftime有點像sprintf,其格式由fmt來指定。
輸入:struct tm *timeptr,const char *format
輸出:const char *buf
%a : 本第幾天名稱,縮寫
%A : 本第幾天名稱,全稱
%b : 月份名稱,縮寫
%B : 月份名稱,全稱
%c : 與ctime/asctime格式相同
%d : 本月第幾日名稱,由零算起
%H : 當天第幾個小時,24小時制,由零算起
%I : 當天第幾個小時,12小時制,由零算起
%j : 當年第幾天,由零算起
%m : 當年第幾月,由零算起
%M : 該小時的第幾分,由零算起
%p : AM或PM
%S : 該分鐘的第幾秒,由零算起
%U : 當年第幾,由第一個日開始計算
%W : 當年第幾,由第一個一開始計算
%w : 當第幾日,由零算起
%x : 當地日期
%X : 當地時間
%y : 兩位數的年份
%Y : 四位數的年份
%Z : 時區名稱的縮寫
%% : %符號
示例:
int main(void)
{
char strtime[20] = {0};
time_t timep;
struct tm *p_tm;
timep = time(NULL);
p_tm = localtime(&timep);
strftime(strtime, sizeof(strtime), "%Y-%m-%d %H:%M:%S", p_tm);
return 0;
}
(12).時間格式化函式 strptime
函式:char * strptime(char *buf,char *format,struct tm *timeptr);
如同scanf一樣,解譯字串成為tm格式
format字串的構建方式和strftime的format字串完全一樣,strptime返回一個指標,
指向轉換過程處理的最後一個字元後面的那個字元,
輸入:const char *buf,const char *format
輸出:struct tm *timeptr
%h : 與%b及%B同
%c : 讀取%x及%X格式
%C : 讀取%C格式
%e : 與%d同
%D : 讀取%m/%d/%y格式
%k : 與%H同
%l : 與%I同
%r : 讀取"%I:%M:%S %p"格式
%R : 讀取"%H:%M"格式
%T : 讀取"%H:%M:%S"格式
%y : 讀取兩位數年份
%Y : 讀取四位數年份
示例:
#include <time.h>
#include <stdio.h>
#include <string.h>
int main() {
struct tm tm;
char buf[255];
strptime("24/Aug/2011:09:42:35", "%d/%b/%Y:%H:%M:%S" , &tm);
printf("asctime:%s",asctime(&tm));
memset(buf,0,sizeof(buf));
strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
printf("%s\n",buf);
return 0;
}
(13).獲得ns級時間clock_gettime
函式: int clock_gettime (clock_t which_clock, struct timespec *tp);
標頭檔案:#include<time.h>
which_clock引數解釋
CLOCK_REALTIME:系統實時時間,隨系統實時時間改變而改變,即從UTC1970-1-1 0:0:0開始計時
CLOCK_MONOTONIC:從系統啟動這一刻起開始計時,不受系統時間被使用者改變的影響
CLOCK_PROCESS_CPUTIME_ID:本程序到當前程式碼系統CPU花費的時間
CLOCK_THREAD_CPUTIME_ID:本執行緒到當前程式碼系統CPU花費的時間
struct timespec結構:
struct timespec{
time_t tv_sec; //秒
long int tv_nsec;//納秒
};
示例:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)
{
struct timespec time_start={0, 0},time_end={0, 0};
clock_gettime(CLOCK_REALTIME, &time_start);
printf("start time %llus,%llu ns\n", time_start.tv_sec, time_start.tv_nsec);
clock_gettime(CLOCK_REALTIME, &time_end);
printf("endtime %llus,%llu ns\n", time_end.tv_sec, time_end.tv_nsec);
printf("duration:%llus %lluns\n", time_end.tv_sec-time_start.tv_sec, time_end.tv_nsec-time_start.tv_nsec);
return 0;
}
執行結果:
start time 1397395863s,973618673 ns
endtime 1397395863s,973633297 ns
duration:0s 14624ns