聊聊时间(3)UTC时间转UNIX时间戳


前一篇文章《聊聊时间(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;
/*step1: 统计从1970年至今年,一共包含多少平年和闰年,并且计算其总秒数*/ 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;
/*step2: 判断今年是平年还是闰年*/ 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;
/*step3. 计算出剩余的时分秒*/ 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

(0)

相关推荐