[底层原理] C/C++获取时间(将时间戳转换为年月日)?

2024-08-24 21:12

本文主要是介绍[底层原理] C/C++获取时间(将时间戳转换为年月日)?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

大家都知道,计算机中存储的时间是一个整数,在现在的编程语言中,可以很方便地将时间戳(整数)转换为字符串,但是如果没有这些我们该如何自己计算出呢?

刚好以前研究过Nginx的源代码,我以他的代码为例,说明其背后的数学原理。当然在工程实践中,没有必要花时间自己实现转换的函数,所以本文用作一些底层原理的研究,说明计算机的背后其实是数学的原理组成的。

我这里采用C语言,如果是其他语言,也是类似的转换方法。

 本文分为两个部分源代码和源代码解析。

环境:Visual Studio 2022,Win11

为了方便后面解析,说明我写代码当天时间是:2024年08月24日,周六

源代码

为了能够在一个单独的console环境中展示,那么我对源代码的命名放在了一起,以下是一个演示的完整代码:

#include <iostream>
#include <ctime>
using namespace std;
typedef struct tm             ngx_tm_t;
typedef intptr_t        ngx_int_t;
void
ngx_gmtime(time_t t, ngx_tm_t* tp)
{ngx_int_t  sec, min, hour, mday, mon, year, wday, yday, days;days = t / 86400;/* Jaunary 1, 1970 was Thursday */wday = (4 + days) % 7;t %= 86400;hour = t / 3600;t %= 3600;min = t / 60;sec = t % 60;/* the algorithm based on Gauss's formula */days = days - (31 + 28) + 719527;year = days * 400 / (365 * 400 + 100 - 4 + 1);yday = days - (365 * year + year / 4 - year / 100 + year / 400);mon = (yday + 31) * 12 / 367;mday = yday - (mon * 367 / 12 - 31);mon += 2;if (yday >= 306) {/** there is no "yday" in Win32 SYSTEMTIME** yday -= 306;*/year++;mon -= 12;if (mday == 0) {/* Jaunary 31 */mon = 1;mday = 31;}else if (mon == 2) {if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) {if (mday > 29) {mon = 3;mday -= 29;}}else if (mday > 28) {mon = 3;mday -= 28;}}/**  there is no "yday" in Win32 SYSTEMTIME**  } else {*      yday += 31 + 28;**      if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) {*          yday++;*      }*/}tp->tm_sec = (int)sec;tp->tm_min = (int)min;tp->tm_hour = (int)hour;tp->tm_mday = (int)mday;tp->tm_mon = (int)mon;tp->tm_year = (int)year;tp->tm_wday = (int)wday;
}int main()
{std::time_t now = std::time(nullptr);ngx_tm_t t;ngx_gmtime(now, &t);// 中国属于东八区,所以我在hour加了一个8std::cout << t.tm_year << "年" << t.tm_mon << "月" << t.tm_mday  << "日 " << t.tm_hour + 8 << ":" << t.tm_min << ":" << t.tm_sec;getchar();}

效果如下,和我的预期一致:

 

源代码解析

先看第11行如下,86400属于什么呢?我直接问gpt,说明是一天的秒数,经过计算确实如此。1 天 = 24 × 60 × 60 秒 = 86400秒。第一步nginx算出了当天到1970年的第一天差距了多少天,

days = t / 86400;

debug查看days的值为19959,也就是说2024年8月24日减去1970年1月1日为19959天:

14行:

wday代表今天是星期几,因为1970年的7月1日为星期四,所以使用上面得到的天数加上4然后余7,得到了wday为6。

wday = (4 + days) % 7;

 

16-17行,执行16行代码后,t 的值会被更新为 t 除以 86400 的余数。这实际上是将时间戳 t 转换为了从当天午夜(00:00:00)开始计算的秒数。换句话说,这行代码去除了时间戳中的日期部分,只保留了时间部分(以秒为单位)。

所以17行除一个小时的秒数,1600秒,得到今天是几点钟了,

t %= 86400;
hour = t / 3600;

debug发现是10点,因为计算机内部时间戳是UTC格式,中国属于东八区,所以其实是18点 ,我后续输出的时候对小时加了一个8。

18-20行,这个时候,t已经是当天过了多少秒了,分钟和秒数以此类推

t %= 3600; // 获取除开小时的秒数
min = t / 60; // 获取当前的分钟数
sec = t % 60; // 获取秒数

到这里已经获取了小时,分钟,秒数、星期几,接下来就是获取年、月、日。

24行

days = days - (31 + 28) + 719527;

经过查找资料才明白 719527 是从公元前1年3月1日到1970年3月1日的天数。所以这行代码是将days改为从公元当天开始到现在的天数。

后续的代码,我后面再继续研究,因为哪个公式看不看懂,也搜索不到。

这篇关于[底层原理] C/C++获取时间(将时间戳转换为年月日)?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103613

相关文章

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

Java通过反射获取方法参数名的方式小结

《Java通过反射获取方法参数名的方式小结》这篇文章主要为大家详细介绍了Java如何通过反射获取方法参数名的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、解决方式方式2.1: 添加编译参数配置 -parameters方式2.2: 使用Spring的内部工具类 -

Go Mongox轻松实现MongoDB的时间字段自动填充

《GoMongox轻松实现MongoDB的时间字段自动填充》这篇文章主要为大家详细介绍了Go语言如何使用mongox库,在插入和更新数据时自动填充时间字段,从而提升开发效率并减少重复代码,需要的可以... 目录前言时间字段填充规则Mongox 的安装使用 Mongox 进行插入操作使用 Mongox 进行更

Java如何获取视频文件的视频时长

《Java如何获取视频文件的视频时长》文章介绍了如何使用Java获取视频文件的视频时长,包括导入maven依赖和代码案例,同时,也讨论了在运行过程中遇到的SLF4J加载问题,并给出了解决方案... 目录Java获取视频文件的视频时长1、导入maven依赖2、代码案例3、SLF4J: Failed to lo

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型