1. 程式人生 > >C語言再學習 -- 時間函式

C語言再學習 -- 時間函式

gmtime函式可以把time函式得到的結果按照格林尼治時間轉換成一個結構體

localtime函式:可以把time函式得到的結果按照當前時區轉換成一個結構體

asctime函式:可以把一個記錄時間的結構體轉換成字串,一般與上兩個函式合用的

格林時間,與北京時間換算,

/* 
    時間函式演示 
 */  
#include <stdio.h>  
#include <time.h>  
int main()  
{  
    time_t tm = 0;//long int別名 //time(0)是一個long int空地址  
    time (&tm);  
    printf ("%s\n", ctime (&tm));  
    struct tm *p_tm = gmtime (&tm);  
    printf ("%s\n", asctime (p_tm));  
    struct tm *p_tm1 = localtime (&tm); //宣告語句  
    printf ("%s\n", asctime (p_tm1));  
    return 0;  
}  
輸出結果:  
Sat Jan 14 14:48:10 2017  
  
Sat Jan 14 06:48:10 2017  
  
Sat Jan 14 14:48:10 2017  

二、Linux獲取時間戳

第一種方法:微秒級時間戳

檢視:man gettimeofday

功能:獲取/設定時間

NAME  
       gettimeofday, settimeofday - get / set time  
  
SYNOPSIS  
       #include <sys/time.h>  
  
       int gettimeofday(struct timeval *tv, struct timezone *tz);  
       int settimeofday(const struct timeval *tv, const struct timezone *tz);  
  
   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):  
  
       settimeofday(): _BSD_SOURCE  
  
DESCRIPTION  
       The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone.  The tv argument is a struct timeval  
       (as specified in <sys/time.h>):  
  
           struct timeval {  
               time_t      tv_sec;     /* seconds */  
               suseconds_t tv_usec;    /* microseconds */  
           };  
  
       and gives the number of seconds and microseconds since the Epoch (see time(2)).  The tz argument is a struct timezone:  
  
           struct timezone {  
               int tz_minuteswest;     /* minutes west of Greenwich */  
               int tz_dsttime;         /* type of DST correction */  
           };  
       If either tv or tz is NULL, the corresponding structure is not set or returned.  

下面是個簡單的例子,用來統計程式的執行時間:

#include <stdio.h>    
#include <sys/time.h>    
    
int main(void)    
{    
    struct timeval start,end;    
    gettimeofday( &start, NULL );  /*測試起始時間*/    
      
    usleep (10000); //使用 usleep  
      
    gettimeofday( &end, NULL );   /*測試終止時間*/    
  
    int timeuse = (end.tv_usec - start.tv_usec);    
    printf("執行時間為:%d us\n",timeuse);    
    
    return 0;    
    
}   
輸出結果:  
10193 us  
第二種方法:毫秒級時間戳,微秒級精度不夠檢視:man ftime功能:返回的日期和時間
NAME
       ftime - return date and time

SYNOPSIS
       #include <sys/timeb.h>

       int ftime(struct timeb *tp);

DESCRIPTION
       This  function  returns  the current time as seconds and milliseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).  The time is
       returned in tp, which is declared as follows:

           struct timeb {
               time_t         time;
               unsigned short millitm;
               short          timezone;
               short          dstflag;
           };

       Here time is the number of seconds since the Epoch, and millitm is the number of milliseconds since time seconds  since  the  Epoch.
       The  timezone  field  is  the local timezone measured in minutes of time west of Greenwich (with a negative value indicating minutes
       east of Greenwich).  The dstflag field is a flag that, if nonzero, indicates that Daylight Saving time applies  locally  during  the
       appropriate part of the year.

       POSIX.1-2001 says that the contents of the timezone and dstflag fields are unspecified; avoid relying on them.

RETURN VALUE
       This function always returns 0.  (POSIX.1-2001 specifies, and some systems document, a -1 error return.)
tp結構定義:
struct timeb{
  time_t time; /* 為1970-01-01至今的秒數*/
  unsigned short millitm; /* 千分之一秒即毫秒 */
  short timezonel; /* 為目前時區和Greenwich相差的時間,單位為分鐘 */
  short dstflag; /* 為日光節約時間的修正狀態,如果為非0代表啟用日光節約時間修正 */
};
下面是個簡單的例子:
#include <stdio.h>  
#include <sys/timeb.h>  
   
long long getSystemTime() {  
    struct timeb t;  
    ftime(&t);  
    return (1000 * t.time + t.millitm) * 1000;  
}  
   
int main() {  
    long long start = getSystemTime();  
    usleep(3000);  
    long long end = getSystemTime();  
   
    printf("time: %lld us\n", end-start);  
    return 0;  
}  
輸出結果:
3000 us
第三種方法:秒級時間戳檢視:man difftime    功能:返回兩個time_t型變數之間的時間間隔,即 計算兩個時刻之間的時間差。
NAME
       difftime - calculate time difference

SYNOPSIS
       #include <time.h>

       double difftime(time_t time1, time_t time0);

DESCRIPTION
       The  difftime()  function returns the number of seconds elapsed between time time1 and time time0, represented as a double.  Each of
       the times is specified in calendar time, which means its value is a measurement (in  seconds)  relative  to  the  Epoch,  1970-01-01
       00:00:00 +0000 (UTC).
下面是個簡單的例子:
#include <stdio.h>  
#include <time.h>  
   
int main(){  
    time_t t_start, t_end;  
    t_start = time(NULL) ;  
    sleep(3);  
    t_end = time(NULL) ;  
    printf("time: %.0f s\n", difftime(t_end,t_start)) ;  
    return 0;  
}  
輸出結果:
time: 3 s
第四種方法:C/C++中的計時函式clock()在MSDN中,查得對clock函式定義如下:
clock_t clock(void) ;
簡單而言,就是該程式從啟動到函式呼叫佔用CPU的時間。這個函式返回從“開啟這個程式程序”到“程式中呼叫clock()函式”時之間的CPU時鐘計時單元(clock tick)數,在MSDN中稱之為掛鐘時間(wal-clock);若掛鐘時間不可取,則返回-1。其中clock_t是用來儲存時間的資料型別
在time.h檔案中,我們可以找到對它的定義:
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
很明顯,clock_t是一個長整形數。在time.h檔案中,還定義了一個常量CLOCKS_PER_SEC它用來表示一秒鐘會有多少個時鐘計時單元,其定義如下:
#define CLOCKS_PER_SEC ((clock_t)1000)
在linux系統下,CLOCKS_PER_SEC的值可能有所不同,目前使用的linux打印出來的值是1000000,表示的是微秒。這一點需要注意。
可以看到每過千分之一秒(1毫秒),呼叫clock()函式返回的值就加1。下面舉個例子,你可以使用公式clock()/CLOCKS_PER_SEC來計算一個程序自身的執行時間:
void elapsed_time()
{
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);
}
當然,你也可以用clock函式來計算你的機器執行一個迴圈或者處理其它事件到底花了多少時間:
#include"time.h"  
#include"stdlib.h"  
#include"stdio.h"  

void sleep (clock_t wait);  

int main (void)  
{  
  long    i = 600000000L;  
  clock_t start, finish;  
  double  duration;  
  
   
  printf( "延時3秒\n" );  
  sleep( (clock_t)3 * CLOCKS_PER_SEC );  
  printf( "Done!\n" );  
  
   
  start = clock();  
  printf("程式啟動,start = %ld\n", start);  

  while( i-- )  
     ;  
  finish = clock();  
  printf("迴圈結束,finish = %ld\n", finish);  

  duration = (double)(finish - start) / CLOCKS_PER_SEC;  
  printf( "CPU 佔用的總時間: %2.1f seconds\n", duration );  
  printf("程式退出...\n");

  return 0; 
}  
  
  
void sleep( clock_t wait )  
{  
  clock_t goal;  
  goal = wait + clock();  
  while( goal > clock() )  
     ;  
}  
輸出結果:
延時3秒
Done!
程式啟動,start = 3000000
迴圈結束,finish = 4810000
CPU 佔用的總時間: 1.8 seconds
程式退出...

它的另一個功能:利用clock()函式和for迴圈完成程式定時暫停
#include <stdio.h>
#include<time.h>
int main(void)
{
	int b = 0, i = 0;
	b=clock()/CLOCKS_PER_SEC;
	for(i=0;i<10;)//完成100秒定時
	{
		i = i-b;
		i = clock()/CLOCKS_PER_SEC;
	}
	printf ("finish\n");
	return 0;
}
輸出結果:
time ./a.out 
finish

real	0m10.171s
user	0m2.180s
sys	0m7.820s
第五種方法:使用time 命令最簡單的方法了,上面的例子其實已經用到。在執行可執行檔案的時候,使用如下命令,便可以統計該程式的執行時間。
time ./a.out 
real	0m10.171s
user	0m2.180s
sys	0m7.820s
time命令,統計的結果包涵程式載入和退出的時間,統計的結果比較粗糙。若想得出函式執行時間較為準確的結果,建議使用上面的幾種方法。
三、定時器:

檢視:man getitimer

NAME  
       getitimer, setitimer - get or set value of an interval timer  
  
SYNOPSIS  
       #include <sys/time.h>  
  
       int getitimer(int which, struct itimerval *curr_value);  
       int setitimer(int which, const struct itimerval *new_value,  
                     struct itimerval *old_value);  
  
DESCRIPTION  
       The system provides each process with three interval timers, each decrementing in a distinct time domain.  When any timer expires, a  
       signal is sent to the process, and the timer (potentially) restarts.  
  
       ITIMER_REAL    decrements in real time, and delivers SIGALRM upon expiration.  
  
       ITIMER_VIRTUAL decrements only when the process is executing, and delivers SIGVTALRM upon expiration.  
  
       ITIMER_PROF    decrements both when the process executes and when the system is executing on behalf of the  process.   Coupled  with  
                      ITIMER_VIRTUAL,  this  timer  is  usually used to profile the time spent by the application in user and kernel space.  
                      SIGPROF is delivered upon expiration.  
  
       Timer values are defined by the following structures:  
  
           struct itimerval {  
               struct timeval it_interval; /* next value */  
               struct timeval it_value;    /* current value */  
           };  
The function getitimer() fills the structure pointed to by curr_value with the current setting for the timer specified by which (one  
       of  ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF).  The element it_value is set to the amount of time remaining on the timer, or zero  
       if the timer is disabled.  Similarly, it_interval is set to the reset value.  
  
       The function setitimer() sets the specified timer to the value in new_value.  If old_value is non-NULL, the old value of  the  timer  
       is stored there.  
  
       Timers decrement from it_value to zero, generate a signal, and reset to it_interval.  A timer which is set to zero (it_value is zero  
       or the timer expires and it_interval is zero) stops.  
  
       Both tv_sec and tv_usec are significant in determining the duration of a timer.  
  
       Timers will never expire before the requested time, but may expire some (short) time afterward, which depends on  the  system  timer  
       resolution  and  on  the system load; see time(7).  (But see BUGS below.)  Upon expiration, a signal will be generated and the timer  
       reset.  If the timer expires while the process is active (always true for ITIMER_VIRTUAL) the signal will be  delivered  immediately  
       when generated.  Otherwise the delivery will be offset by a small time dependent on the system loading.  
  
RETURN VALUE  
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.  

第一個引數:計時器的型別
ITIMER_REAL--真實計時器,主要描述程序執行的真實時間,通過產生SIGALRM訊號工作(掌握)
ITIMER_VIRTUAL 虛擬計時器,主要描述程序在使用者空間消耗的時間,通過產生SIGVTALRM訊號工作(瞭解)
ITIMER_PROF--實用計時器,主要描述程序在使用者空間和核心空間共同消耗的時間,通過產生SIGPROF訊號工作(瞭解)
第二個引數:計時器的新值
struct itimerval 
{
struct timeval it_interval; /* next value */    //間隔時間
struct timeval it_value;    /* current value */ //啟動時間
};
struct timeval 
{
long tv_sec;   /* seconds */       //秒數
long tv_usec;  /* microseconds */  //微秒
};
第三個引數:用於獲取計時器的舊值,不想帶直接給NULL
函式功能:主要用於使用者獲取/設定計時器的數值

下面是個簡單的例子:

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

void fa(int signo)
{
	printf("貪吃蛇移動了一步\n");
}

int main()
{
	struct itimerval t_start, t_end;
	getitimer (ITIMER_REAL, &t_start);
	printf("Start time: %ld us\n", t_start.it_value.tv_usec);
	
	//設定SIGALRM進行自定義處理
	signal(SIGALRM,fa);

	struct itimerval timer;
	//設定啟動時間
	timer.it_value.tv_sec=0;//秒數
	timer.it_value.tv_usec=30000;//微秒
	//設定間隔時間
	timer.it_interval.tv_sec=1;
	timer.it_interval.tv_usec=0;
	//設定真實計時器開始工作
	int res=setitimer(ITIMER_REAL,&timer,NULL);
	if(-1==res)
	{
		perror("settimer"),exit(-1);
	}
	
	getitimer (ITIMER_REAL, &t_end);
	printf("End time: %ld us\n", t_end.it_value.tv_usec);
	
	long cost_time = t_end.it_value.tv_usec - t_start.it_value.tv_usec;
	printf("Cost time: %ld us\n", cost_time);
	while (1);
	return 0;
}
輸出結果:
Start time: 0 us
End time: 29997 us
Cost time: 29997 us 
貪吃蛇移動了一步
貪吃蛇移動了一步
貪吃蛇移動了一步
貪吃蛇移動了一步
貪吃蛇移動了一步
^C

擴充套件:

1、預定義巨集裡有 __TIME__

__TIME__原始檔編譯時間,格式為“hh: mm: ss”

#include <stdio.h>  
int main (void)  
{   
    printf ("The time is %s\n", __TIME__);  
    return 0;  
}  
輸出結果:   
The time is 18:24:24

2、標頭檔案 time.h
日期和時間函式: 本類別給出時間和日期處理函式
----------------------------------------

下面的函式感興趣的可以自行百度
時間操作函式得到處理器時間 clock
得到時間差difftime
設定時間mktime
得到時間time
時間轉換函式 得到以ASCII碼錶示的時間asctime
得到字串表示的時間ctime
得到指定格式的時間strftime

__BEGIN_NAMESPACE_STD
/* Time used by the program so far (user time + system time).
   The result / CLOCKS_PER_SECOND is program time in seconds.  */
extern clock_t clock (void) __THROW;

/* Return the current time and put it in *TIMER if TIMER is not NULL.  */
extern time_t time (time_t *__timer) __THROW;

/* Return the difference between TIME1 and TIME0.  */
extern double difftime (time_t __time1, time_t __time0)
     __THROW __attribute__ ((__const__));

/* Return the `time_t' representation of TP and normalize TP.  */
extern time_t mktime (struct tm *__tp) __THROW;


/* Format TP into S according to FORMAT.
   Write no more than MAXSIZE characters and return the number
   of characters written, or 0 if it would exceed MAXSIZE.  */
extern size_t strftime (char *__restrict __s, size_t __maxsize,
            __const char *__restrict __format,
            __const struct tm *__restrict __tp) __THROW;
__END_NAMESPACE_STD
3、根據檔案時間戳的相關屬性來查詢檔案

我們可以使用 stat 命令來檢視一個檔案的時間資訊,如下:

[email protected]:/mnt/test# stat ./  
  檔案:"./"  
  大小:4096       塊:8          IO 塊:4096   目錄  
裝置:801h/2049d   Inode:291601      硬連結:2  
許可權:(0755/drwxr-xr-x)  Uid:( 1000/    zslf)   Gid:( 1000/    zslf)  
最近訪問:2016-11-25 09:45:24.699140785 +0800  
最近更改:2016-11-25 09:45:22.255140690 +0800  
最近改動:2016-11-25 09:45:22.255140690 +0800  
建立時間:-  
-atime、-mtime、-ctime、-amin、-mmin、-cmin

這裡的 -atime、-mtime、-ctime 分別對應的是 “最近一次訪問時間”,“最近一次內容修改時間”,“最近一次屬性修改時間”,這裡的atime的單位指的是“天”,amin 的單位是分鐘。

檔案的 Access time,atime:是在讀取檔案或者執行檔案時更改的。
檔案的 Modified time,mtime: 是在寫入檔案時隨檔案內容的更改而更改的。
檔案的 Create time,ctime :是在寫入檔案、更改所有者、許可權或連結設定時隨 Inode 的內容更改而更改的。

檔案各種事件標記的顯示方法

ls -lc filename         列出檔案的 ctime 
ls -lu filename         列出檔案的 atime 
ls -l filename          列出檔案的 mtime  

檢視:man ls

-c     with  -lt:  sort  by,  and show, ctime (time of last modification of file status information) with -l: show ctime and sort by
              name otherwise: sort by ctime, newest first

-u     with -lt: sort by, and show, access time with -l: show access time and sort by name otherwise: sort by access time

-l     use a long listing format
查詢在五天內沒有訪問過的檔案  
[email protected]:/mnt/test# find ./ -atime +5  
查詢在五天內訪問過的檔案  
[email protected]:/mnt/test# find ./ -atime -5  
./  
./f.sh  
./g.sh  
./a.sh  
./c.sh  
./b.sh 
4、UNIX時間戳