各位小伙伴們,大家好,本文是農(nóng)歷辛丑年本公眾號(hào)所發(fā)表的第一篇文章。時(shí)光如梭,短短的一年又過去了,不禁時(shí)時(shí)感嘆時(shí)間之匆匆。就好像朱自清說的“我的日子滴在時(shí)間的流里,沒有聲音,也沒有影子”。既然說到了時(shí)間這個(gè)話題,本文就借此來詳細(xì)地聊一下時(shí)間。本文中接下來的內(nèi)容可能會(huì)涉及到天文,地理,歷史,計(jì)算機(jī)等方面的知識(shí)。但不會(huì)涉及到相對(duì)論等宏觀的宇宙學(xué)原理。
1 歷法與時(shí)間
世界上主流的歷法根據(jù)參照物的不同可以分為陰歷和陽歷。所謂陰歷是以月亮作為計(jì)時(shí)參照物的歷法,陽歷是以太陽作為計(jì)時(shí)參照物的歷法。在人類過去的幾千年發(fā)展歷程中,有各種各樣標(biāo)準(zhǔn)的陰歷和陽歷,這些歷法的計(jì)時(shí)準(zhǔn)確度各不相同。當(dāng)然,中國古代的歷法嚴(yán)格意義上來說應(yīng)該被稱為農(nóng)歷而不是陰歷,因?yàn)檗r(nóng)歷不僅有著以陰歷為基礎(chǔ)的計(jì)時(shí)系統(tǒng),還有著以“二十四節(jié)氣”為代表的陽歷計(jì)時(shí)系統(tǒng)。
近代以來,隨著西方工業(yè)革命后歐洲的崛起,它的歷法“格里高利歷”(1582年頒行)也被全世界絕大多數(shù)國家所使用,這個(gè)“格里高利歷”即為我們俗稱的“公歷”。公元,是紀(jì)年法稱謂,為紀(jì)年體系。該紀(jì)年法是以耶穌誕生為公元元年,公元元年之前的稱公元前。所謂的2020年就是從公元元年開始算起的兩千零二十年。在公歷紀(jì)年系統(tǒng)中,規(guī)定了一年有365天(平年)每4年產(chǎn)生一個(gè)閏年(366天)。因此,普通年份能被4整除,且不能被100整除的,是閏年(如2004年就是閏年),世紀(jì)年份能被400整除的是閏年(如2000年是閏年,1900年不是閏年)。
以上是對(duì)紀(jì)年法的簡述,仔細(xì)回想一下,我們精確地表述某一時(shí)刻的時(shí)候,一般表述為:XXXX年XX月XX日XX時(shí)XX分XX秒。由此可以看出,一個(gè)精準(zhǔn)的時(shí)刻是由“年月日時(shí)分秒”這六個(gè)部分組成的,而這六個(gè)部分中,可以大體分成兩類,一類是由“年月日”組成的日期,第二類是由“時(shí)分秒”組成的時(shí)間。第一類是與我們之前講述的紀(jì)年法相關(guān),第二類則完完全全是由時(shí)間所組成。
在現(xiàn)代歷法中,一天由24個(gè)小時(shí)組成,這個(gè)大家都知道。但是,由于我們地球是一個(gè)球體,,因此導(dǎo)致了地球是自西向東自轉(zhuǎn),東邊比西邊先看到太陽,東邊的時(shí)間也比西邊的早。東邊時(shí)刻與西邊時(shí)刻的差值要以時(shí)計(jì),而且還要以分和秒來計(jì)算,這給人們帶來不便。
為了克服時(shí)間上的混亂,1884年在華盛頓召開的一次國際經(jīng)度會(huì)議(又稱國際子午線會(huì)議)上,規(guī)定將全球劃分為24個(gè)時(shí)區(qū)(東、西各12個(gè)時(shí)區(qū))。規(guī)定英國(格林尼治天文臺(tái)舊址)為中時(shí)區(qū)(零時(shí)區(qū))、東1—12區(qū),西1—12區(qū)。每個(gè)時(shí)區(qū)橫跨經(jīng)度15度,時(shí)間正好是1小時(shí)。最后的東、西第12區(qū)各跨經(jīng)度7.5度,以東、西經(jīng)180度為界。每個(gè)時(shí)區(qū)的中央經(jīng)線上的時(shí)間就是這個(gè)時(shí)區(qū)內(nèi)統(tǒng)一采用的時(shí)間,稱為區(qū)時(shí),相鄰兩個(gè)時(shí)區(qū)的時(shí)間相差1小時(shí)。如圖1所示。
圖1 世界時(shí)區(qū)圖
2 GMT和UTC和UNIX時(shí)間戳
GMT,即格林尼治標(biāo)準(zhǔn)時(shí)間,也就是世界時(shí)。GMT的正午是指當(dāng)太陽橫穿格林尼治子午線(本初子午線)時(shí)的時(shí)間。但由于地球自轉(zhuǎn)不均勻不規(guī)則,導(dǎo)致GMT不精確,現(xiàn)在已經(jīng)不再作為世界標(biāo)準(zhǔn)時(shí)間使用。
UTC,即協(xié)調(diào)世界時(shí)。UTC是以原子時(shí)秒長為基礎(chǔ),在時(shí)刻上盡量接近于GMT的一種時(shí)間計(jì)量系統(tǒng)。為確保UTC與GMT相差不會(huì)超過0.9秒,在有需要的情況下會(huì)在UTC內(nèi)加上正或負(fù)閏秒。UTC現(xiàn)在作為世界標(biāo)準(zhǔn)時(shí)間使用。
所以,UTC與GMT基本上等同,誤差不超過0.9秒。
計(jì)算機(jī)中的UNIX時(shí)間戳,是以GMT/UTC時(shí)間(1970-01-01T00:00:00)為起點(diǎn),到具體時(shí)間的秒數(shù),不考慮閏秒。這么做當(dāng)然是為了簡化計(jì)算機(jī)對(duì)時(shí)間操作的復(fù)雜度。
比如我的電腦現(xiàn)在的系統(tǒng)時(shí)間為2021年3月5日21點(diǎn)23分0秒,因?yàn)槲业碾娔X默認(rèn)時(shí)區(qū)為東8區(qū),則0時(shí)區(qū)的時(shí)間為2021年3月5日13點(diǎn)23分0秒,則UNIX時(shí)間戳為1614950580秒。
有了上面準(zhǔn)備知識(shí)之后,有一個(gè)問題需要大家思考,計(jì)算機(jī)(RTC芯片或者RTC模塊)到底是如何來存儲(chǔ)時(shí)間的?很顯然,有了上述的鋪墊之后,我們可以知道,所有的RTC模塊或者RTC芯片其內(nèi)部只不過是一個(gè)計(jì)數(shù)器,準(zhǔn)確地說應(yīng)該是(秒)計(jì)數(shù)器,它在工作時(shí),受秒晶振觸發(fā),每一秒計(jì)數(shù)一次。
當(dāng)我們需要讀取時(shí)間的時(shí)候,就用軟件或者硬件的手段將UNIX時(shí)間戳轉(zhuǎn)換成UTC時(shí)間,然后根據(jù)計(jì)算機(jī)的時(shí)區(qū),將其修正為當(dāng)前時(shí)區(qū)的時(shí)間。
當(dāng)我們需要設(shè)置時(shí)間的時(shí)候,芯片使用軟件或者硬件手段將需要設(shè)置的當(dāng)前時(shí)區(qū)的時(shí)間先轉(zhuǎn)成UTC時(shí)間,接著將UTC時(shí)間轉(zhuǎn)換成UNIX時(shí)間戳,最后將其寫入RTC模塊或者芯片的計(jì)數(shù)器存儲(chǔ)器里面。
3 為何我們還需要研究UNIX時(shí)間戳轉(zhuǎn)換成UTC時(shí)間的代碼?
既然我們現(xiàn)在有了眾多的RTC模塊,為什么還要來研究UNIX時(shí)間戳如何轉(zhuǎn)換成UTC時(shí)間呢?這個(gè)話題的開展,是源于STM32F103系列單片機(jī)的使用。眾所周知,STM32單片機(jī)全系擁有RTC功能,但是對(duì)于STM32F103系列的單片機(jī),它的RTC時(shí)鐘非常簡單,歸根到底,它就是一個(gè)32位數(shù)據(jù)長度的非易失性秒計(jì)數(shù)器(VBAT引腳保證不掉電)。它并沒有任何功能模塊可以將這個(gè)計(jì)數(shù)器里面的時(shí)間轉(zhuǎn)換成UTC時(shí)間,你能得到的僅僅是一個(gè)32位的寄存器數(shù)值,這個(gè)RTC寄存器會(huì)在你設(shè)置的初始計(jì)數(shù)值的前提下,每1秒進(jìn)行自加,其內(nèi)部簡化結(jié)構(gòu)如圖2所示。
圖2 STM32F103 內(nèi)部RTC簡化結(jié)構(gòu)圖
因此,我們?nèi)绻胍褂眠@個(gè)RTC來進(jìn)行時(shí)間計(jì)數(shù)時(shí),最簡單標(biāo)準(zhǔn)的做法如下:
(1)當(dāng)用戶需要校準(zhǔn)時(shí)間時(shí),先將用戶設(shè)置的當(dāng)?shù)貢r(shí)區(qū)時(shí)間轉(zhuǎn)換成UTC時(shí)間,然后將UTC時(shí)間轉(zhuǎn)換成UNIX時(shí)間戳寫入RTC計(jì)數(shù)器,RTC計(jì)數(shù)器更新完成初始時(shí)間后,進(jìn)行秒自加;
(2)當(dāng)用戶程序需要讀取時(shí)間時(shí),先將當(dāng)前RTC計(jì)數(shù)器中的UNIX時(shí)間戳讀出,然后將其轉(zhuǎn)換成UNIX時(shí)間戳轉(zhuǎn)換成UTC時(shí)間,最后,將UTC時(shí)間轉(zhuǎn)換成當(dāng)?shù)貢r(shí)間進(jìn)行顯示。
具體步驟如圖3所示。
圖3 讀取STM32F103中RTC的步驟
接下來的文章中,我們將會(huì)詳細(xì)討論UNIX時(shí)間戳和UTC時(shí)間的轉(zhuǎn)換算法。
聯(lián)系客服