前一篇文章《聊聊時間(2)UNIX時間戳轉UTC時間》中,我們詳細地解釋了如何將一個32位無符號的UNIX時間戳利用軟體算法轉換成我們可以看得懂的UTC時間。我們說,在STM32F10x系列無萬年曆功能的RTC系統中,如果要將RTC中的計數值顯示出來,那麼需要利用UNIX時間戳轉UTC時間算法。但是如果需要設置一個時鐘的時間,那還需要先將當前時區的時間轉換成UTC時間,再將UTC時間轉換成UNIX時間戳寫入RTC的32位寄存器中。今天的文章,我們就來聊聊如何將UTC時間轉換成UNIX時間戳。
UTC時間轉換成UNIX時間戳
UTC時間轉換成UNIX時間戳的方法其實很簡單,因為此條件下輸入的年月日是固定的。因此對於這個問題,我們可以直接按照年月日時分的形式進行計算,統計每它們的秒數之和。最後加入最後的秒數就可以得到當前的UNIX時間戳了。我們知道閏年的秒數為31622400s,平年的秒數為31536000s。
程序的設計思路為:
(1)統計從1970年至今一共過了多少平年,多少閏年,統計完成之後,根據閏年和平年的秒數計算出從1970年1月1日至今年一共經過了多少秒。這一部分的代碼如圖1所示。
圖1 閏年和平年秒數轉換
(2)計算出當前年份是平年還是閏年,以此推算出從年初到上個月過去了多少天。計算完成之後,可以將本月的到昨天的天數一起統計進來,最終可以將年月日三個單位的秒數一起統計出來。具體代碼如圖2所示。
圖2 月和日轉換成UNIX時間戳秒數
(3)將剩餘的時分秒利用同樣的方式進行累加,最終得出當前的UNIX時間戳。其最終的代碼如圖3所示。
圖3 最終完成的代碼。
我們可以簡單做個測試,將日期設置成2021年2月5日8時6分7秒,運行程序計算出當前的UNIX時間戳為1612512367s,再將1612512367s時間戳輸入到我們上一篇文章中UNIX時間戳轉UTC時間的代碼裡,看看最終結果,如圖4所示。
圖4 UNIX時間戳和UTC時間互相轉換
由圖4可知,我們的測試結果完全正確。當然對於這種計算比較繁瑣的程序,可以使用單元測試全部測試一遍,以排除深層的BUG。
本文全部代碼:
1.timex_test.c
#include <stdio.h>#include "timex_test1.h"time_tt stCurrentTime;int main(void){ stCurrentTime.year = 2021; stCurrentTime.month = 2; stCurrentTime.date = 5; stCurrentTime.hour = 8; stCurrentTime.minute = 6; stCurrentTime.second = 7; printf("%ds", UTCToUnixTimeStamp(&stCurrentTime)); return 0;}UnixTimeStamp_t UTCToUnixTimeStamp(time_tt *time){ int FlatYearMonthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int LeapYearMonthDay[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; time_tt *tempTime; int i; tempTime = time; int LeapYearNumber; int FlatYearNumber; int ThisYear; int LastMonDays = 0; UnixTimeStamp_t TimeStamp = 0;
for ( i = UNIX_TIME_STAMP_YEAR; i < tempTime->year; i ++ ) { if((((i % 4) == 0) && ((i % 100) != 0)) || ((i % 400) == 0)) { LeapYearNumber ++; } else { FlatYearNumber ++; } } TimeStamp = LeapYearNumber * 31622400 + FlatYearNumber * 31536000;
if((((tempTime->year % 4) == 0) && ((tempTime->year % 100) != 0)) || ((tempTime->year % 400) == 0)) { ThisYear = LEAP_YEAR; } else { ThisYear = FLAT_YEAR; }
for ( i = 1; i < tempTime->month; i ++) { if(ThisYear == LEAP_YEAR) { LastMonDays += LeapYearMonthDay[i]; } else if(ThisYear == FLAT_YEAR) { LastMonDays += FlatYearMonthDay[i]; } } LastMonDays = LastMonDays + tempTime->date - 1; TimeStamp += LastMonDays * 86400;
TimeStamp += tempTime->hour * 3600; TimeStamp += tempTime->minute * 60; TimeStamp += tempTime->second; return TimeStamp;}2.timex_test.h
#ifndef __TIMEX_TEST1_H_#define __TIMEX_TEST1_H_
#define UNIX_TIME_STAMP_YEAR 1970#define LEAP_YEAR 1#define FLAT_YEAR 0typedef struct { int year; int month; int date; int hour; int minute; int second;} time_tt;
typedef unsigned int UnixTimeStamp_t;
UnixTimeStamp_t UTCToUnixTimeStamp(time_tt *time);#endif