[底层原理] 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

相关文章

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

Python获取浏览器Cookies的四种方式小结

《Python获取浏览器Cookies的四种方式小结》在进行Web应用程序测试和开发时,获取浏览器Cookies是一项重要任务,本文我们介绍四种用Python获取浏览器Cookies的方式,具有一定的... 目录什么是 Cookie?1.使用Selenium库获取浏览器Cookies2.使用浏览器开发者工具

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分