1. 程式人生 > >一個小C問題:計算從1970年到某一時期所經歷的秒數

一個小C問題:計算從1970年到某一時期所經歷的秒數

部落格目錄:

      一、常識;

      二、常用的函式舉例;

      三、解決一個問題;

                                                                                    正文如下

一、常識;

          Unix時間戳(Unix timestamp),或稱Unix時間(Unix time)、POSIX時間(POSIX time),是一種時間表示方式,定義為從格林威治時間1970年01月01日00時00分00秒起至現在的總秒數。Unix時間戳不僅被使用在Unix 系統、類Unix系統中,也在許多其他作業系統中被廣告採用。

          目前相當一部分作業系統使用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秒)則基本不會遇到這類溢位問題。

本地時間(locale time)
格林威治時間(Greenwich Mean Time GMT)
時間協調時間 (Universal Time Coordinated UTC)

先看看時間的標準:
(1)世界時 
世界時是最早的時間標準。在1884年,國際上將1s確定為全年內每日平均長度的1/8.64×104。以此標準形成的時間系統,稱為世界是,即UT1。1972年國際上開始使用國際原子時標,從那以後,經過格林威治老天文臺本初子午線的時間便被稱為世界時,即UT2,或稱格林威治時間(GMT),是對地球轉速週期性差異進行校正後的世界時。 
(2)原子時 
1967年,人們利用銫原子振盪週期極為規律的特性,研製出了高精度的原子時鐘,將銫原子能級躍遷輻射9192631770周所經歷的時間定為1s。現在用的時間就是1971年10月定義的國際原子時,是通過世界上大約200多臺原子鐘進行對比後,再由國際度量衡局時間所進行資料處理,得出的統一的原子時,簡稱TAI。 
(3)世界協調時 
世界協調時是以地球自轉為基礎的時間標準。由於地球自轉速度並不均勻,並非每天都是精確的86400原子s,因而導致了自轉時間與世界時之間存在18個月有1s的誤差。為糾正這種誤差,國際地球自轉研究所根據地球自轉的實際情況對格林威治時間進行增減閏s的調整,與國際度量衡局時間所聯合向全世界釋出標準時間,這就是所謂的世界協調時(UTC:CoordinatdeUniversalTime)。UTC的表示方式為:年(y)、月(m)、日(d)、時(h)、分(min)、秒(s),均用數字表示。

GPS 系統中有兩種時間區分,一為UTC,另一為LT(地方時)兩者的區別為時區不同,UTC就是0時區的時間,地方時為本地時間,如北京為早上八點(東八區),UTC時間就為零點,時間比北京時晚八小時,以此計算即可
  通過上面的瞭解,我們可以認為格林威治時間就是世界協調時間(GMT=UTC),格林威治時間和UTC時間均用秒數來計算的。

大家都知道,在計算機中看到的utc時間都是從(1970年01月01日 0:00:00)開始計算秒數的。所看到的UTC時間那就是從1970年這個時間點起到具體時間共有多少秒。

linux下儲存時間常見的有兩種儲存方式,一個是從1970年到現在經過了多少秒一個是用一個結構來分別儲存年月日時分秒的
time_t 這種型別就是用來儲存從1970年到現在經過了多少秒
;

而直接儲存年月日的是一個結構:
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;  /*月, 從一月算起,0-11*/  1+p->tm_mon;
    int tm_year;  /*年 從1900至今已經多少年*1900+ p->tm_year;
    int tm_wday; /*星期,一週中的第幾天, 從星期日算起,0-6*/
    int tm_yday; /*從今年1月1日到目前的天數,範圍0-365*/
    int tm_isdst; /*日光節約時間的旗標*/
};

需要特別注意的是,年份是從1900年起至今多少年,而不是直接儲存如2011年,月份從0開始的,0表示一月,星期也是從0開始的, 0表示星期日,1表示星期一。

二、常用的函式舉例;


mktime(將時間結構資料轉換成經過的秒數)
表頭檔案
#include<time.h>
定義函式
time_t mktime(strcut tm * timeptr);
函式說明
mktime()用來將引數timeptr所指的tm結構資料轉換成從公元1970年1月1日0時0分0 秒算起至今的UTC時間所經過的秒數。
返回值
返回經過的秒數。
範例
/* 用time()取得時間(秒數),利用localtime()
轉換成struct tm 再利用mktine()將struct tm轉換成原來的秒數*/
#include<time.h>
main()
{
time_t timep;
strcut tm *p;
time(&timep);
printf(“time() : %d \n”,timep);
p=localtime(&timep);
timep = mktime(p);
printf(“time()->localtime()->mktime():%d\n”,timep);
}
執行
time():974943297
time()->localtime()->mktime():974943297
 函式名: difftime
功  能: 計算兩個時刻之間的時間差
用  法: double difftime(time_t time2, time_t time1);
程式例:

#include <time.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>

int main(void)
{
   time_t first, second;

   clrscr();
   first = time(NULL);  /* Gets system
      time */
   delay(2000);         /* Waits 2 secs */
   second = time(NULL); /* Gets system time
      again */

   printf("The difference is: %f \
   seconds\n",difftime(second,first));
   getch();

   return 0;
} 

 三、解決一個問題;

注意:time_t 只能表示從 1970年1月1日0時0分0秒 到此時的秒數,1970年1月1日0時0分0秒 以前的時間它是無法表示的。而 struct tm 的成員變數 tm_year 的值為實際年份減去 1900

#include "stdio.h"

#include "time.h"


int main()

{

time_t t1,t2;

struct tm timeptr1,timeptr2;


timeptr1.tm_mday=1;

timeptr1.tm_mon=1;

timeptr1.tm_year=1971-1900;

timeptr1.tm_sec=timeptr1.tm_min=timeptr1.tm_hour=

timeptr1.tm_wday=timeptr1.tm_yday=timeptr1.tm_isdst=0;


timeptr2.tm_mday=2;

timeptr2.tm_mon=1;

timeptr2.tm_sec=5;

timeptr2.tm_year=1971-1900;

timeptr2.tm_min=timeptr2.tm_hour=timeptr2.tm_wday=

timeptr2.tm_yday=timeptr2.tm_isdst=0;


t1=mktime(&timeptr1);

t2=mktime(&timeptr2);

printf("時間差:\n>>  %lf\n",difftime(t2,t1));


system("pause");

return 0;

}


參考文獻:

             http://blog.csdn.net/luoweifu/article/details/20288549

              http://ganquan.info/standard-c/function/difftime

             http://zhidao.baidu.com/link?url=BVGWN7Ahj3oyPcyD_ItWgTy2H_Qx7-V9Dt5pIhdIGwurRryRLtBhIjtHMQpwdfnCkR3avAjBAwt5cswrvs_59a