时间戳,相信很多相关专业的人,计算机软件电子等等都会听过。由于最早是由Unix系统使用所以又叫Unix时间戳。
Unix 时间戳(Unix Timestamp)定义为从UTC(世界协调时)/GMT(格林尼治时)的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒,我们不需要考虑进位,只需要记录秒数。
所以时间戳只需要比较大的一个计数器即可记录时间。
UTC/GMT介绍
GMT(Greenwich Mean Time)格林尼治标准时间是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准。(伦敦标准时间)
注意:由于引力潮汐种各样的因素其实地球自转时间是不断变慢,导致时间基础不准确;
UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒。当原子钟计时一天的时间与地球自转一周的时间相差超过0.9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致。
注意:闰秒机制:由于地球受到潮汐,引力变化等等因素影响自转一周时间是不固定的,假设:时间会偏慢开始可能差1或者0.9秒才有24h,此时我们可以把UTC设置为2进1,来等待GMT时间减小误差,使得两个同步。
时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间。
优点:1简化硬件电路,.只需要一个比较大的寄存器存储秒数即可;
2.计算差值方便,只需要计算两个时间戳之间的差值,不需要考虑单位转化;
缺点:占用软件资源,时间戳往往比较大运算较为费时间;
时间戳的起点也就是:伦敦时间1970-1-1 0:0:0为起点开始计数秒数;
所以为我们之需要将时间戳进行转化,就可以很简单的计算出当前的时间;
那么具体的计算,就可以参考''time.h''里面如何计算。
对于我们使用时间戳而言主要:利用时间戳来实现时间的转换,具体的转换过程C语言当中已经完善在<time.h>当中我们只需要调用函数转换时间戳即可。
接下来主要是对于time.h的介绍,我截图来自菜鸟编程,自己感兴趣也可以去看看详细介绍
首先time当中封装好了变量:
以及分装好的库函数:
主要是针对于各种时间戳的函数,方便我们处理我这里演示几个常用的:
1.time_t time(time_t *seconds)可以用来获取当前时间戳,我们可以通过传递整数地址,也可以通过直接,接收返回值获取当前时间戳。
注意:该函数只适用于在线系统,我们可以获取电脑当中的时间戳,而对于离线系统例如后面STM32离线系统,它本身的计数器为空需要我们传递值,所以无法从中获取时间戳。
示例:
#include <stdio.h>
#include "time.h"
int main()
{
time_t test_time = 0;//此处采用time.h当中定义的32位无符号整形,也可以自定义
test_time = time(NULL);
printf("时间戳test_time:%d\n", test_time);
time_t test_time2 = 0;
time(&test_time2);
printf("时间戳test_time2:%d\n", test_time);
return 0;
}
效果:
2.struct tm *gmtime(const time_t *timer):用于获取在GMT/UTC条件下我们对于时间戳的处理,返回的是tm的结构体:
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
int tm_min; /* 分,范围从 0 到 59 */
int tm_hour; /* 小时,范围从 0 到 23 */
int tm_mday; /* 一月中的第几天,范围从 1 到 31 */
int tm_mon; /* 月份,范围从 0 到 11 */
int tm_year; /* 自 1900 起的年数 */
int tm_wday; /* 一周中的第几天,范围从 0 到 6 */
int tm_yday; /* 一年中的第几天,范围从 0 到 365 */
int tm_isdst; /* 夏令时 */
};
我们通过传递时间戳的地址,就可以返回tm结构体数据。
实例代码:
#include <stdio.h>
#include "time.h"
time_t time_cnt;
struct tm time_data;
int main()
{
/*time_cnt=time(NULL);*/
/*time(&time_cnt);*/
time_cnt =1705582640;
time_data= *gmtime(&time_cnt);
printf("伦敦日期:%d-%d-%d\n",time_data.tm_year+1900, time_data.tm_mon + 1, time_data.tm_mday);
printf("伦敦时间:%d:%d:%d\n", time_data.tm_hour, time_data.tm_min, time_data.tm_sec);
return 0;
}
实际运行效果:
注意:我们需要注意这里面的年份,月份,小时,和时间戳定义的1970年1月1日0时0秒定义是不一样的,实际使用需要自己添加偏移。
其次获取到的是伦敦时间和日期,需要注意。
3.struct tm* localtime(const time_t*);就是在上面基础上增加了时区的偏移,不需要我们自己手动增加偏移,注意:是根据在线系统自己定位当前时区自己添加偏移,对于离线系统单片机而言实际效果和struct tm *gmtime(const time_t *timer)相同;
#include <stdio.h>
#include "time.h"
time_t time_cnt;
struct tm time_data;
int main()
{
/*time_cnt=time(NULL);*/
/*time(&time_cnt);*/
time_cnt =1705582640;
time_data= *localtime(&time_cnt);
printf("北京日期:%d-%d-%d\n",time_data.tm_year+1900, time_data.tm_mon + 1, time_data.tm_mday);
printf("北京时间:%d:%d:%d\n", time_data.tm_hour, time_data.tm_min, time_data.tm_sec);
return 0;
}
运行效果:
4.time_t mktime(struct tm *timeptr),就是把tm结构体转化为时间戳秒数的函数。
我们可以通过传递时间日期结构体,来获取时间戳,一般我们用于RTC当中,定义日期的数组
然后获取时间戳,传递给单片机。用户更改时间,只需要照着更改日期时间结构体即可简单易懂。
示例代码:
#include <stdio.h>
#include "time.h"
struct tm time_data;
time_t time_cnt;
int main()
{
time_data.tm_year = 2024 - 1900;
time_data.tm_mon = 1 - 1;
time_data.tm_mday = 4;
time_data.tm_hour = 0;
time_data.tm_min = 0;
time_data.tm_sec = 1;
time_data.tm_isdst = -1;
time_cnt = mktime(&time_data);
printf("时间戳:%d\n", time_cnt);
return 0;
}
运行结果:
5.char* ctime(const time_t*);主要是把时间戳转化为字符串,方便打印函数直接打印。
6.char *asctime(const struct tm *timeptr) C 库函数 char *asctime(const struct tm *timeptr) 返回一个指向字符串的指针,它代表了结构 struct timeptr 的日期和时间。传回来的是一个日期时间的字符串指针。
实例代码:
#include <stdio.h>
#include <string.h>
#include <time.h>
int main()
{
struct tm t;
t.tm_sec = 50;
t.tm_min = 02;
t.tm_hour = 22;
t.tm_mday = 18;
t.tm_mon = 1-1;
t.tm_year = 2024-1900;
t.tm_wday = 4;
puts(asctime(&t));
return(0);
}
运行结果:
过多的函数不做讲解,具体可以参考time.h,可以通过定义或者看菜鸟教程C学习。