当前位置: 首页 > article >正文

基于面向对象设计的C++日期推算引擎:精准高效的时间运算实现与运算重载工程化实践

前引: 在软件开发中,时间与日期的处理是基础但极具挑战性的任务。传统的手工日期运算逻辑往往面临闰年规则、月份天数动态变化、时区转换等复杂场景的容错难题,且代码冗余度高、可维护性差。本文将深入探讨如何利用C++的面向对象特性与成员函数封装能力,构建一个高内聚、低耦合的日期推算系统。

 本文目的:深度 巩固+运用 C++运算符重载成员函数,细节夯实!

目录

实践引入

运算符重载实践—日期比大小

类的创建

日期比较

日期相等判断

 日期小于判断

日期小于等于判断

日期大于判断

日期大于等于判断

总结

运算符重载实践—日期推算

类的创建

日期推算(后)

计算当月天数

日期进位计算

测试

变式

 日期推算(前)

日期退位计算

测试 

日期推算(前置++)

测试

日期推算(前置--)

测试

 日期推算(后置--)

测试

 运算符重载实践—日期间隔


实践引入

我们日常生活中对于日期的使用很广泛,例如:距离高考***天、今天是*年*月*日.......

大家可以点击下面这个链接体验一下对于时间的计算:

https://onlinealarmkur.com/date/zh-cn/https://onlinealarmkur.com/date/zh-cn/

最近咱们学习的类和对象中 运算符重载成员函数 就可以来简单实现这个功能!

运算符重载实践—日期比大小

类的创建

既然是日期计算,那么还和上面的类一样,需要有年、月、日

class Timedate
{
public://构造函数Timedate(int year = 2025, int month = 5, int day = 9){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};
日期比较
日期相等判断

咱们得成员函数可以只在类里面进行声明,在另一个文件来完成函数的实现,需要注明函数来历!

//成员函数定义
bool Timedate::operator==(const Timedate St2)
{if (_year == St2._year && _month ==St2._month && _day == St2. _day){return true;}return false;
}

注意咱们的函数调用,以下两种调用方式是相等的(为了体验运算符重载的简洁性,选第二种)

St1 == St2;St1.operator==(St2);
 日期小于判断

按照上面的流程,我们先在成员函数里面声明

bool operator<(const Timedate St2);

然后跨文件实现该函数的定义

bool Timedate::operator<(const Timedate St2)
{if (_year < St2._year){return true;}if (_year == St2._year && _month < St2._month){return true;}if (_year == St2._year && _month == St2._month && _day < St2._day){return true;}return false;
}

日期小于等于判断

还是先写成员函数声明

bool operator<=(const Timedate St2);

随后重点来了!

第一种:我们可以和上面一样,通过 if 语句去判断来返回不同的值

第二种:咱们小于等于的判断不就是前面两个结合起来吗?所以我们可以调用上面两个函数,如下

bool Timedate::operator<=(const Timedate St2)
{return ((*this) < St2 || (*this) == St2);
}

 这里隐藏的 this 指针是指向 St1 的,这里其实跟函数调用一样,只是需要理解隐藏的 this 指针

St1 < St2;
(*this) < St2;
//二者等价
日期大于判断

有了前面的基础,我们同样有两种写法:

第一种:走 if 判断

第二种:“大于”条件不是刚好和“小于等于”相反吗!所以我们还是采用调用函数的方法来实现

bool operator>(const Timedate St2);
bool Timedate::operator>(const Timedate St2)
{return !((*this) < St2 || (*this) == St2);
}
日期大于等于判断

第一种:直接走 if 判断

第二种:调用运算符重载函数(大于等于与小于刚好互补)如下:

bool operator>=(const Timedate St2);
bool Timedate::operator>=(const Timedate St2)
{return !((*this) < St2);
}
总结

(1)运算符重载成员函数大大减少了代码量

(2)其次增加了代码表达的效果,对比之前的函数:需要有函数名、参数,而现在我们根据运算符就可以明了的判断出这个函数的功能,这是很直观的,较C语言一个大的进阶!

St1 == St2
St1 < St2
St1 <= St2
St1 > St2
St1 >= St2

运算符重载实践—日期推算

类的创建

 既然是日期计算,那么还和上面的类一样,需要有年、月、日

class Timedate
{
public://构造函数Timedate(int year = 2025, int month = 5, int day = 9){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};
日期推算(后)

功能:给一个天数,自当前日期开始,推算一定天数之后的日期

计算当月天数

功能:计算给定的这个月有多少天

因为会面临加法计算,对月或者年需要进位,所以我们需要知道当月的准确天数是多少

设计功能:

(1)可以通过 case 语句判断当月天数,最后判断是不是闰年,因为闰年的2月有29天

(2)通过 if 语句判断,根据给定的月直接确定天数,再走闰年的判断

//计算当月天数
int Timedate::Compute(int _year, int _month)
{//我们这里就拿case语句判断switch (_month){case 1:case 3:case 5:case 7:case 8:case 10:case 12:return 31;case 4:case 6:case 9:case 11:return 30;case 2:if (_year % 4 == 0 && _year % 100 != 0 || _year % 400 == 0){return 29;}elsereturn 28;}
}

下面我们来测试一下这个功能:

日期进位计算

我们只需要在一个循环对年、月进行进位计算,等循环结束再将剩余天数相加即可

不管咋样,我们直接加上天数,然后根据对应月的满天数去减即可

注意:我们是推算对应天数之后,所以不改变原来的日期,需要建立新对象

//推算进位
Timedate Timedate::operator+(int day)
{//既然是加,那么我们不能改变原来的日期,调用拷贝构造Timedate St3(*this);//对月进位St3._day += day;while (St3._day > Compute(St3._year,St3._month)){//日减少St3._day -= Compute(St3._year, St3._month);//月增加St3._month++;//如果超过12月,年进位,重置月份if (St3._month > 12){St3._year++;St3._month = 1;}}return St3;
}
测试

变式

上面是不改变原来的日期,如果我们现在需要改变呢?

很简单,我们只需要调用刚才的函数,再利用编译器默认的运算符重载函数赋值即可

函数声明:

Timedate& operator+=(int day);

函数实现:

Timedate& Timedate::operator+=(int day)
{return *this = ((*this) + 100);
}

然后利用编译器默认的运算符重载函数进行浅拷贝内置类型

这里补充一下:

因为我们没有写“等于”的运算符重载函数,编译器就会调用自己默认的运算符重载函数完成

(1)对内置类型发生浅拷贝

(2)自定义类型调用自己的重载函数(会直接更改地址) 

 日期推算(前)

有了上面的经验,日期推算前就是往前推一定天数之前的日期是多少

类的结构还是与上面的一样,下面我们来完成函数

日期退位计算
Timedate operator-(int day);

执行函数:

先更新月、再根据月判断年,最后更新天数

 
Timedate Timedate::operator-(int day)
{//先拷贝构造一个一模一样的对象,防止更改原来的日期Timedate St3(*this);//直接减去天数St3._day -= day;while (St3._day < 1){//小于1说明不符合规定//应该先减月St3._month--;//如果月小于1,说明要更新年了if (St3._month < 1){St3._year--;St3._month = 12;}//再加天数St3._day += Compute(St3._year, St3._month);}return St3;
}
测试 

日期推算(前置++)

前置加加是返回加完之后的结果,这点需要和后置加加区别。类的类型不变,我们直接进入函数

函数声明:

Timedate& operator++();

 函数实现:

Timedate& Timedate::operator++()
{//此时this指针传过来的就是调用函数的对象_day++;while (_day > Compute(_year, _month)){//如果超过当月天数_day -= Compute(_year, _month);//月加1_month++;//判断12月以上的情况if (_month > 12){_year++;_month = 1;}}return *this;
}

注意*this指向的对象是调用函数的对象,是全局生命域,所以可以使用引用

测试

日期推算(前置--)

函数声明:

Timedate& operator--();

函数实现:

Timedate& Timedate::operator--()
{_day --;//如果不满足月的要求,就退治while (_day < 1){_month--;if (_month < 1){_month = 12;_year--;}_day += Compute(_year, _month);}return *this;
}
测试

 日期推算(后置--)

后置唯一需要注意的是它的函数调用与前置减减达成重复,所以我们需要用一个参数进行区分

函数声明:

Timedate operator--(int);

函数实现:

Timedate Timedate::operator--(int)
{//拷贝构造Timedate St3(*this);_day--;while (_day < 1){_month--;if (_month < 1){_month = 12;_year--;}_day += Compute(_year, _month);}return St3;
}
测试

 运算符重载实践—日期间隔

有了上面的基础我们完成这个功能就很简单了!

第一种:最简单的多次调用“加加”函数,每调用一次,计数一次

第二种:分区段(第一次保证年相同,第二次再保证月、日相同)实现

第一种更加的直观,所以我们选择第一种!
函数声明:

int operator-(const Timedate St2);

函数实现:

(1)为了避免改变原对象,我们新建两个临时对象

(2)先假设其中一个对象较大,如果假设不成立,再将二者调换

(3)通过循环来多次调用“相等”运算重载函数,并且不断计数

(4)根据假设结果返回正负值,来直观的判断日期先后

int Timedate::operator-(const Timedate St2)
{//假设第一个参数更大Timedate St3 = (*this);Timedate St4 = St2;//用于返回正负值int flag = 1;//计数int date = 0;//调用运算重载函数确定大小if (St3 < St4){St3 = St4;St4 = *this;flag = -1;}//计算差值while (!( St3 == St4)){++St4;++date;}return flag * date;
}

                                                【雾非雾】期待与你的下次相遇! 

相关文章:

基于面向对象设计的C++日期推算引擎:精准高效的时间运算实现与运算重载工程化实践

前引&#xff1a; 在软件开发中&#xff0c;时间与日期的处理是基础但极具挑战性的任务。传统的手工日期运算逻辑往往面临闰年规则、月份天数动态变化、时区转换等复杂场景的容错难题&#xff0c;且代码冗余度高、可维护性差。本文将深入探讨如何利用C的面向对象特性与成员函数…...

如何把 Microsoft Word 中所有的汉字字体替换为宋体?

Ctrl H &#xff0c;然后&#xff0c;点击更多&#xff0c;勾选使用通配符&#xff0c;查找内容中填入 [一-龥]{1,}&#xff0c; 这是 Word 通配符匹配汉字的经典写法&#xff08;匹配 Unicode 范围内的 CJK 汉字&#xff09;。 然后&#xff0c; “替换为”留空&#xff0c;点…...

02. [Python+Golang+PHP]三数之和,多种语言实现最优解demo

一、问题描述&#xff1a;三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中…...

MongoDB选择理由

1.简介 MongoDB是一个基于分布式文件存储的数据库由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。Mongo最大的特点是…...

倚光科技在二元衍射面加工技术上的革新:引领光学元件制造新方向​

倚光科技二元衍射面加工技术&#xff08;呈现出细腻的光碟反射纹路&#xff09; 在光学元件制造领域&#xff0c;二元衍射面的加工技术一直是行业发展的关键驱动力之一。其精准的光相位调制能力&#xff0c;在诸多前沿光学应用中扮演着不可或缺的角色。然而&#xff0c;长期以来…...

驱动开发(2)|鲁班猫rk3568简单GPIO波形操控

上篇文章写了如何下载内核源码、编译源码的详细步骤&#xff0c;以及一个简单的官方demo编译&#xff0c;今天分享一下如何根据板子的引脚写自己控制GPIO进行高低电平反转。 想要控制GPIO之前要学会看自己的引脚分布图&#xff0c;我用的是鲁班猫RK3568&#xff0c;引脚分布图如…...

《软件工程》第 3 章 -需求工程概论

在软件工程的开发流程中&#xff0c;需求工程是奠定项目成功基础的关键环节。它专注于获取、分析、定义和管理软件需求&#xff0c;确保开发出的软件能真正满足用户需求。接下来&#xff0c;我们将按照目录内容&#xff0c;结合 Java 代码和实际案例&#xff0c;深入讲解需求工…...

VMware-MySQL主从

MySQL主从 服务器信息 服务器类型角色主机地址主机名称虚拟机master192.168.40.128test-1虚拟机slave192.168.40.129test-2 Master 配置&#xff08;192.168.40.128&#xff09; 删除自动生成的配置 /var/lib/mysql/auto.cnf [roottest-1 ~]# rm -rf /var/lib/mysql/auto.…...

ArcGIS Pro 3.4 二次开发 - 几何

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 几何1 空间参考1.1 从已知ID构建空间参考1.2 从字符串构建空间参考1.3 使用 WGS84 空间参考1.4 使用已知ID构建带有垂直坐标系的空间参考1.5 使用垂直坐标系从字符串构建SpatialReference1.6 使用自定义投影坐标系(PCS)构建空间参…...

2023-ICLR-ReAct 首次结合Thought和Action提升大模型解决问题的能力

关于普林斯顿大学和Google Research, Brain Team合作的一篇文章, 在语言模型中协同Reasoning推理和Action行动。 论文地址&#xff1a;https://arxiv.org/abs/2210.03629 代码&#xff1a;https://github.com/ysymyth/ReAct.git 其他复现 langchain &#xff1a;https://pytho…...

Rust 开发的一些GUI库

最近考虑用Rust干点什么&#xff0c;于是搜集了下资料——根据2025年最新调研结果和社区实践&#xff0c;Rust GUI库生态已形成多个成熟度不同的解决方案。以下是当前主流的GUI库分类及特点分析&#xff0c;结合跨平台支持、开发体验和实际应用场景进行综合评估&#xff1a; 一…...

【第四十六周】文献阅读:从 RAG 到记忆:大型语言模型的非参数持续学习

目录 摘要Abstract从 RAG 到记忆&#xff1a;大型语言模型的非参数持续学习研究背景方法论1. 离线索引&#xff08;Offline Indexing&#xff09;2. 在线检索&#xff08;Online Retrieval&#xff09;具体细节 创新性实验结果局限性总结 摘要 本论文旨在解决当前检索增强生成…...

从智能提效到产品赋能的架构实践

摘要 本文深入探讨了企业级系统从智能化提效阶段向产品赋能阶段演进的架构实践路径。通过分析传统架构的局限性,提出了以用户价值为导向的现代化架构设计理念,并结合实际案例展示了如何构建可扩展、高可用、智能化的产品架构体系。 1. 引言 在数字化转型的浪潮中,企业技术…...

《Python 虚拟环境完全指南:如何管理项目依赖,避免版本冲突》

《Python 虚拟环境完全指南:如何管理项目依赖,避免版本冲突》 1. 引言 在 Python 开发中,依赖管理是至关重要的环节。不同项目可能需要不同的库版本,而全局安装库可能导致版本冲突或环境污染。为解决这一问题,Python 提供了虚拟环境(venv、virtualenv),帮助开发者隔离…...

微信小程序带数组参数跳转页面,微信小程序跳转页面带数组参数

在微信小程序中&#xff0c;带数组参数跳转页面需要通过JSON序列化和URL编码处理&#xff0c;以下是具体实现方法 传递数组参数‌&#xff08;发送页面&#xff09; wx.navigateTo({url: /pages/targetPage?arr encodeURIComponent(JSON.stringify(yourArray)) });接收数组参…...

服务器开机自启动服务

前言&#xff1a; 将服务器中脚本开启自启动执行 步骤&#xff1a; 1.创建一个 systemd 服务文件: /etc/systemd/system/ 目录下创建一个新的服务文件。例如&#xff0c;命名为 myapp.service&#xff1a; sudo nano /etc/systemd/system/myapp.service2.编写 [Unit] Descri…...

关于OT IIOT系统远程访问的零信任安全

什么是OT & IIOT&#xff1f;—— 工业领域的“操作基石”与“智能升级” 在工业数字化转型的浪潮中&#xff0c;OT&#xff08;运营技术&#xff09;与IIoT&#xff08;工业物联网&#xff09;是两个核心概念。前者是工业生产的“神经中枢”&#xff0c;后者是驱动智能升…...

【Doris基础】Apache Doris vs 传统数据仓库:架构与性能的全面对比

目录 1 引言 1.1 传统数据仓库的发展 1.2 现代分析型数据库的崛起 2 核心架构对比 2.1 传统数据仓库的架构 2.2 Doris的架构设计 3 关键技术差异 3.1 存储引擎对比 3.2 查询执行对比 3.3 数据摄入方式对比 4 性能与扩展性对比 4.1 性能基准对比 4.2 扩展性对比 5…...

【VScode】python初学者的有力工具

还记得23年11月&#xff0c;我还在欣喜Spyder像Rstudio一样方便。 但苦于打开软件打开太卡、太耗时&#xff08;初始化-再加载一些东西&#xff09;&#xff0c;一度耗费了我学习的热情。 就在24年5月份&#xff0c;别人推荐下发现了一个更加轻量级、方便又快速的ID&#xff0…...

Linux系统中为Qt项目封装一个udp客户端类

Linux系统中为Qt项目封装一个udp客户端类 一、场景 在日常的Qt项目中,我们常用的就是网络通信协议是TCP/UDP, 对于网络协议,Qt都已经封装好了自己的TCP/UDP类,QTcpSocket/QUdpSocket,这些类非常的好用,也非常的易用。 这些类继承自QAbstractSocket,而QAbstractSocket类…...

443端口:HTTPS通信的安全基石

在互联网通信中&#xff0c;端口是数据传输的虚拟通道&#xff0c;每个端口对应特定的服务或协议。其中&#xff0c;443端口 作为 HTTPS协议 的默认端口&#xff0c;在现代网络安全中扮演着至关重要的角色。 一、443端口的核心作用 HTTPS加密通信 443端口是HTTPS&#xff08;…...

宝塔安装WordPress程序

宝塔安装WordPress程序 一、提前准备1&#xff0c;下载WordPress2&#xff0c;在宝塔创建站点 二、部署项目1&#xff0c;上传下载的wordpress压缩包至创建的项目根目录下并解压 三、wordpress安装1&#xff0c;在浏览器打开创建的网站2&#xff0c;开始按照流程安装配置数据库…...

Agent 的7 中设计模式

这里写自定义目录标题 建立有效的Agent什么是Agent&#xff1f;何时&#xff08;以及何时不使用&#xff09;使用代理何时以及如何使用框架构建块、工作流和Agent构建模块&#xff1a;增强型LLM(The augmented LLM)工作流程&#xff1a;提示链接(Prompt chaining)工作流程&…...

OpenGAN:基于开放数据生成的开放集识别

简介 简介&#xff1a;这次学习的OpenGAN主要学习一个思路&#xff0c;跳出传统GAN对于判断真假的识别到判断是已知种类还是未知种类。重点内容不在于代码而是思路&#xff0c;会简要给出一个设计的代码。 论文题目&#xff1a;OpenGAN: Open-Set Recognition via Open Data …...

【node】Express创建服务器

Express是基于Node.js平台&#xff0c;快速、开放、极简的Web开发框架。基于http的express是专门用来创建web服务器的&#xff0c;可以极大的提高开发效率。 Express的创建的服务器 1 web网站服务器 专门对外提供web网页资源的服务器 2 Api接口服务器 专门对外提供Api接口的服…...

使用 OpenCV 实现哈哈镜效果

在计算机视觉和图像处理领域&#xff0c;OpenCV 提供了非常强大的图像几何变换能力&#xff0c;不仅可以用于纠正图像&#xff0c;还能制造各种“有趣”的视觉效果。今天&#xff0c;我们就来实现一个经典的“哈哈镜”效果&#xff0c;让图像像在游乐园里一样被拉伸、压缩、扭曲…...

DeepSeek-R1-0528 模型最新发布:编程推理能力跃升

2025年5月28日&#xff0c;深度求索&#xff08;DeepSeek&#xff09;通过Hugging Face平台悄然发布推理模型DeepSeek-R1-0528 Hugging Face Deepseek-R1-0528模型地址。尽管官方称其为"minor update"&#xff0c;但社区实测显示&#xff0c;该版本在编程能力、复杂推…...

git仓库服务gogs详解

Gogs&#xff08;Go Git Service&#xff09;是一个使用 Go 编写的自助 Git 服务&#xff0c;旨在提供一个轻量级、易部署、高效的 Git 代码托管平台。它类似于 GitHub、GitLab&#xff0c;但更轻量&#xff0c;非常适合私有化部署、小型团队和嵌入式环境。下面是对 Gogs 的详细…...

PaddleNLP 的文本分类项目

以下是一个基于 PaddleNLP 的文本分类项目&#xff0c;按照标准工程结构组织&#xff0c;并包含测试数据集和完整流程。这个示例使用ERNIE模型处理IMDB电影评论情感分析任务。 项目工程结构 ernie_sentiment_analysis/ ├── data/ # 数据集目录 │ ├─…...

git 一台电脑一个git账户,对应多个仓库ssh

生成ssh # 为账户A生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "your_email_for_account_Aexample.com" -f ~/.ssh/id_ed25519 # 为账户B生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "your_email_for_account_Bexample.com" -f ~/.ssh/id_rsa_yswq进入文件…...