Unix时间戳

21 篇文章 4 订阅
11 篇文章 2 订阅

目录

Unix时间戳

参考文章: 

GMT / UTC

时间戳转换

简介

库变量

库宏

库函数

time_t

struct tm

char *

time()函数

转换成日期时间

转换伦敦时间

转换当地时间

日期时间转换为秒计数器(当地时间)

时间转换成字符串

秒计数器转换为字符串(默认格式)

日期时间转换为字符串(默认格式)

日期时间转换为字符串(自定义格式)


Unix时间戳

Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒

时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量

世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间

UNIX时间戳的0按照ISO 8601规范为 :1970-01-01T00:00:00Z.

一个小时表示为UNIX时间戳格式为:3600秒;一天表示为UNIX时间戳为86400秒,闰秒不计算。

在大多数的UNIX系统中UNIX时间戳存储为32位,这样会引发2038年问题或Y2038。

目前看秒是10位10位数

毫秒是13位10位数

时间 | 秒

1 分钟 | 60

1 小时 | 3600

1 天 | 86400

1 周 | 604800

1 月 (30.44 天) | 2629743

1年 (365.24 天) | 31556736

参考文章: 

什么是unix时间戳 - 知乎 (zhihu.com)

http://t.csdnimg.cn/6Lp0J

http://t.csdnimg.cn/6V5hV

http://t.csdnimg.cn/M7SKE

http://t.csdnimg.cn/s6I9B


后面会讲BKP和RTC外设结构

BKP备份寄存器,需要VBAT引脚提供备用电源来维持


知识补充

GMT / UTC

GMT(Greenwich Mean Time)格林尼治标准时间是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准

UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒。当原子钟计时一天的时间与地球自转一周的时间相差超过0.9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致


时间戳转换

time.h教程网站:C 标准库 – <time.h> | 菜鸟教程 (runoob.com)

简介

time.h 头文件定义了四个变量类型、两个宏和各种操作日期和时间的函数。

库变量

下面是头文件 time.h 中定义的变量类型:

序号变量 & 描述
1size_t
是无符号整数类型,它是 sizeof 关键字的结果。
2clock_t
这是一个适合存储处理器时间的类型。
3time_t is
这是一个适合存储日历时间的类型。
4struct tm
这是一个用来保存时间和日期的结构。

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;       /* 夏令时                */
};

库宏

下面是头文件 time.h 中定义的宏:

序号宏 & 描述
1NULL
这个宏是一个空指针常量的值。
2CLOCKS_PER_SEC
这个宏表示每秒的处理器时钟个数。

库函数

下面是头文件 time.h 中定义的函数:

序号函数 & 描述
1char *asctime(const struct tm *timeptr)
返回一个指向字符串的指针,它代表了结构 timeptr 的日期和时间。
2clock_t clock(void)
返回程序执行起(一般为程序的开头),处理器时钟所使用的时间。
3char *ctime(const time_t *timer)
返回一个表示当地时间的字符串,当地时间是基于参数 timer。
4double difftime(time_t time1, time_t time2)
返回 time1 和 time2 之间相差的秒数 (time1-time2)。
5struct tm *gmtime(const time_t *timer)
timer 的值被分解为 tm 结构,并用协调世界时(UTC)也被称为格林尼治标准时间(GMT)表示。
6struct tm *localtime(const time_t *timer)
timer 的值被分解为 tm 结构,并用本地时区表示。
7time_t mktime(struct tm *timeptr)
把 timeptr 所指向的结构转换为一个依据本地时区的 time_t 值。
8size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。
9time_t time(time_t *timer)
计算当前日历时间,并把它编码成 time_t 格式。

 C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换

time_t

默认__time64_t,实际上就是__int64,实际上就是64位有符号整形数据~

struct tm

struct tm组合在一起,代表一个结构体类型名,后面自定义变量名(没有使用typedef,和STM32库函数的结构体方式是一样的效果)

从VScode转到这个结构体的定义,和上面菜鸟教程里的数据稍微有一些出入

struct tm
{ /* A structure for storing the attributes of a broken-down time; (once
   * again, it isn't defined elsewhere, so no guard is necessary).  Note
   * that we are within the scope of <time.h> itself, so we must provide
   * the complete structure declaration here.
   */
  int  tm_sec;  	/* Seconds: 0-60 (to accommodate leap seconds) */
  int  tm_min;  	/* Minutes: 0-59 */
  int  tm_hour; 	/* Hours since midnight: 0-23 */
  int  tm_mday; 	/* Day of the month: 1-31 */
  int  tm_mon;  	/* Months *since* January: 0-11 */
  int  tm_year; 	/* Years since 1900 */
  int  tm_wday; 	/* Days since Sunday (0-6) */
  int  tm_yday; 	/* Days since Jan. 1: 0-365 */
  int  tm_isdst;	/* +1=Daylight Savings Time, 0=No DST, -1=unknown */
};

char *

【[C语言] 指针的详解与应用-理论结合实践,真正理解指针!】 https://www.bilibili.com/video/BV1Mb4y1X7dz/?share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933

time()函数

获取系统时钟,这个函数可以直接读取电脑的时间,但是在STM32里不能读取时间;因为STM32是一个离线的裸机系统,不知道时间是多少

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    time_cnt = time(NULL); // 参数不知道,给一个空参数
    printf("%d\n", time_cnt);

    return 0;
}

输出结果:

带入时间戳转换工具网站   时间戳(Unix timestamp)转换工具 - 在线工具 (tool.lu)

现在时间~2024年2月19日15:46:43

用输出参数的方法获取时间

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    time_cnt = time(NULL); // 参数不知道,给一个空参数
    printf("%d\n", time_cnt);

    time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    printf("%d\n", time_cnt);

    return 0;
}

输出结果:

手动给一个时间数值,用PPT上的时间   北京时间  2023-1-1  23:59:55

转换成日期时间

接着把这个数据转换成日期时间的格式

转换伦敦时间

调用struct tm* gmtime(const time_t*);函数,秒计数器转换为日期时间(转换成格林尼治时间)

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    time_cnt = time(NULL); // 参数不知道,给一个空参数
    printf("%d\n", time_cnt);

    time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换时间\n");                       // 手动赋值
    time_data = *gmtime(&time_cnt);             // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year);          // 年
    printf("%d\n", time_data.tm_mon);           // 月
    printf("%d\n", time_data.tm_mday);          // 日
    printf("%d\n", time_data.tm_hour);          // 时
    printf("%d\n", time_data.tm_min);           // 分
    printf("%d\n", time_data.tm_sec);           // 秒
    printf("%d\n", time_data.tm_wday);          // 星期

    printf("Hello World!\r\n");

    return 0;
}

输出结果:

123年0月1日,15时59分55秒,星期0(星期天),这样的输出结果不对呀!!!

根据程序的定义,年是从1900年经过的年数,月是从1月经过的月数,所以代码里要加上这个偏移数据

修正之后的代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    time_cnt = time(NULL); // 参数不知道,给一个空参数
    printf("%d\n", time_cnt);

    time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换时间\n");                       // 手动赋值
    time_data = *gmtime(&time_cnt);             // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900);   // 年
    printf("%d\n", time_data.tm_mon + 1);       // 月
    printf("%d\n", time_data.tm_mday);          // 日
    printf("%d\n", time_data.tm_hour);          // 时
    printf("%d\n", time_data.tm_min);           // 分
    printf("%d\n", time_data.tm_sec);           // 秒
    printf("%d\n", time_data.tm_wday);          // 星期

    printf("Hello World!\r\n");

    return 0;
}

修正之后输出结果:

现在输出的伦敦时间(格林尼治时间)能与PPT的时间对应上

转换当地时间

调用struct tm* localtime(const time_t*);函数,秒计数器转换为日期时间(当地时间)

localtime函数和gmtime函数作用是相同的,是指localtime会根据市区自动添加小时的偏移

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    // time_cnt = time(NULL); // 参数不知道,给一个空参数
    // printf("%d\n", time_cnt);

    // time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    // printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换为本地时间\n");
    time_data = *localtime(&time_cnt);        // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900); // 年
    printf("%d\n", time_data.tm_mon + 1);     // 月
    printf("%d\n", time_data.tm_mday);        // 日
    printf("%d\n", time_data.tm_hour);        // 时
    printf("%d\n", time_data.tm_min);         // 分
    printf("%d\n", time_data.tm_sec);         // 秒
    printf("%d\n", time_data.tm_wday);        // 星期

    printf("Hello World!\r\n");

    return 0;
}

使用loacltime函数输出结果:

这个函数会根据电脑的设置,自动判断我们处于哪个时区,时间添加偏移,输出数据

成功判断我们在东8区,与手动赋值的北京时间一致

日期时间转换为秒计数器(当地时间)

time_t mktime(struct tm*);

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    // time_cnt = time(NULL); // 参数不知道,给一个空参数
    // printf("%d\n", time_cnt);

    // time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    // printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换为本地时间\n");
    time_data = *localtime(&time_cnt);        // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900); // 年
    printf("%d\n", time_data.tm_mon + 1);     // 月
    printf("%d\n", time_data.tm_mday);        // 日
    printf("%d\n", time_data.tm_hour);        // 时
    printf("%d\n", time_data.tm_min);         // 分
    printf("%d\n", time_data.tm_sec);         // 秒
    printf("%d\n", time_data.tm_wday);        // 星期

    //上面的逆过程~再转换成秒
    time_cnt = mktime(&time_data);
    printf("日期时间转换为秒计数器:%d\n", time_cnt);

    printf("Hello World!\r\n");

    return 0;
}

输出结果:

可以看到,mktime()函数转换完之后,能和手动赋值的北京时间对应上,并且是当地时间

time_t mktime(struct tm*);函数前面没加const,这个参数struct tm*即是输入参数,又是输出参数,给定年月日,再给出时分秒,就能转换成秒,即可顺带算出是星期几,回填到参数struct tm*

时间转换成字符串

秒计数器转换为字符串(默认格式)

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    // time_cnt = time(NULL); // 参数不知道,给一个空参数
    // printf("%d\n", time_cnt);
    // time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    // printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换为本地时间\n");
    time_data = *localtime(&time_cnt);        // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900); // 年
    printf("%d\n", time_data.tm_mon + 1);     // 月
    printf("%d\n", time_data.tm_mday);        // 日
    printf("%d\n", time_data.tm_hour);        // 时
    printf("%d\n", time_data.tm_min);         // 分
    printf("%d\n", time_data.tm_sec);         // 秒
    printf("%d\n", time_data.tm_wday);        // 星期

    // 上面的逆过程~再转换成秒
    time_cnt = mktime(&time_data);
    printf("日期时间转换为秒计数器:%d\n", time_cnt);

    time_str = ctime(&time_cnt);
    printf(time_str); // 打印这个字符串

    return 0;
}

输出结果:

输出默认的时间格式,内容是,星期天、一月一、23:59:55、2023年

日期时间转换为字符串(默认格式)

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    // time_cnt = time(NULL); // 参数不知道,给一个空参数
    // printf("%d\n", time_cnt);
    // time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    // printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换为本地时间\n");
    time_data = *localtime(&time_cnt);        // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900); // 年
    printf("%d\n", time_data.tm_mon + 1);     // 月
    printf("%d\n", time_data.tm_mday);        // 日
    printf("%d\n", time_data.tm_hour);        // 时
    printf("%d\n", time_data.tm_min);         // 分
    printf("%d\n", time_data.tm_sec);         // 秒
    printf("%d\n", time_data.tm_wday);        // 星期

    // 上面的逆过程~再转换成秒
    time_cnt = mktime(&time_data);
    printf("日期时间转换为秒计数器:%d\n", time_cnt);

    time_str = ctime(&time_cnt); // 秒计数器转换为字符串(默认格式)
    printf(time_str);            // 打印这个字符串

    time_str = asctime(&time_data); // 日期时间转换为字符串(默认格式)
    printf(time_str);               // 打印这个字符串

    return 0;
}

输出结果:

日期时间转换为字符串(自定义格式)

C 库函数 – strftime() | 菜鸟教程 (runoob.com)

size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)

  • 第一个参数 - 字符数组
  • 第二个参数 - 数组长度
  • 第三个参数 - 格式字符串
  • 第四个参数 - 日期时间

代码:

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

time_t time_cnt; // 实际上是int64类型数据
struct tm time_data;
char *time_str;

int main(void)
{
    // time_cnt = time(NULL); // 参数不知道,给一个空参数
    // printf("%d\n", time_cnt);
    // time(&time_cnt); // 形参给 输出参数的地址,和上面那一句作用相同
    // printf("%d\n\n", time_cnt);

    time_cnt = 1672588795;                      // 北京时间  2023-1-1  23:59:55
    printf("手动赋值北京时间:%d\n", time_cnt); // 手动赋值
    printf("转换为本地时间\n");
    time_data = *localtime(&time_cnt);        // 把手动赋值时间的地址传入进去,返回值是struct tm*,所以取内容(不能指针跨级赋值)
    printf("%d\n", time_data.tm_year + 1900); // 年
    printf("%d\n", time_data.tm_mon + 1);     // 月
    printf("%d\n", time_data.tm_mday);        // 日
    printf("%d\n", time_data.tm_hour);        // 时
    printf("%d\n", time_data.tm_min);         // 分
    printf("%d\n", time_data.tm_sec);         // 秒
    printf("%d\n", time_data.tm_wday);        // 星期

    // 上面的逆过程~再转换成秒
    time_cnt = mktime(&time_data);
    printf("日期时间转换为秒计数器:%d\n", time_cnt);

    time_str = ctime(&time_cnt); // 秒计数器转换为字符串(默认格式)
    printf(time_str);            // 打印这个字符串

    time_str = asctime(&time_data); // 日期时间转换为字符串(默认格式)
    printf(time_str);               // 打印这个字符串

    char t[50];
    strftime(t, 50, "%H-%M-%S", &time_data);
    printf(t); // 打印这个字符串

    return 0;
}

输出结果:

按照指定格式打印了   小时-分钟-秒

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北国无红豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值