C++写一个Date日期类

一个日期类作为类和对象知识点的总结
注意:
因为历史上1582年10月是少了10天,并且闰年的计算规则在1582年前后是不同的,因此计算某一天是周几,直接采用了倒推的方式确定公元1年1月1日是周几,然后反过来写的。(仅仅为了省事)

Date.h

#pragma once
/* 一个类可以重载那些运算符,取决于哪些运算符对这个类型有意义! */
class Date {
public://对Date类声明友元friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in,  Date& d);//构造函数Date(int year=1,int month = 1,int day = 1):_year(year),_month(month),_day(day){//检查日期合法性if (!checkDate()) {assert(checkDate());}}//拷贝构造Date(const Date& d) :_year(d._year),_month(d._month),_day(d._day){}//赋值重载 d1=d2=d3,最后返回d1Date& operator=(const Date& d){//防止自我赋值if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}bool isLeapYear(int year) {if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))return true;return false;}int getLeapNum(int begin, int end) {if (begin > end)	return 0;int leap1 = (begin - 1) / 4 - (begin - 1) / 100 + (begin - 1) / 400;int leap2 = end / 4 - end / 100 + end / 400;return leap2 - leap1;}//获取某年某月天数,频繁调用->放在类里定义作为内联//构造频繁,直接放在类里面当作内联int getMonthDay(int year, int month) {static int months[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//如果是2月且闰年if (_month == 2 && isLeapYear(year))return 29;return months[month];}//日期合法性bool checkDate() {if (_year >= 1&& _month && _month < 13&& _day>0 && _day <= getMonthDay(_year, _month)){return true;}return false;}//比较运算符bool operator==(const Date& d);bool operator!=(const Date& d);bool operator>(const Date& d);bool operator<(const Date& d);bool operator>=(const Date& d);bool operator<=(const Date& d);//日期+-天数Date operator+(int day);Date& operator+=(int day);Date operator-(int day);Date& operator-=(int day);//operator++Date& operator++();//前置Date operator++(int);//后置//日期-日期int operator-(const Date& d);//operator--Date& operator--();Date operator--(int);int operator-(const Date& d) const;//计算是周几string DayofWeek();
private:int _year;int _month;int _day;
};//cout << d1 << d2,频繁调用,函数声明和定义不分离 直接内联
inline ostream& operator<<(ostream& out, const Date& d) {out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}//cin>>d1>>d2, 需要改变Date对象 不能用const引用
inline istream& operator>>(istream& in,Date& d) {in >> d._year >> d._month >> d._day;//检查输入日期合法assert(d.checkDate());return in;
}

Date.cpp

#define _CRT_SECURE_NO_WARNINGS	
#include<iostream>
#include<assert.h>
using namespace std;#include "Date.h"//比较运算符
bool Date::operator==(const Date& d) {return _year == d._year&& _month == d._month&& _day == d._day;
}
bool Date::operator!=(const Date& d) {return !(*this == d);
}
bool Date::operator>(const Date& d) {if (_year > d._year || _year == d._year && _month > d._month ||_year == d._year && _month == d._month && _day > d._day){return true;}return false;
}
bool Date::operator<(const Date& d) {return !(*this >= d);
}
bool Date::operator>=(const Date& d) {return *this == d || *this > d;
}
bool Date::operator<=(const Date& d) {return !(*this > d);
}//日期+=天数: d1+=d2+=100
Date& Date::operator+=(int day) {//处理day是负数的情况: +=负数 -> -=正数if (day < 0) {return *this -= -day;}//先把天数加上,然后判断是否超过当月的天数_day += day;while (_day > getMonthDay(_year, _month)) {_day -= getMonthDay(_year, _month);++_month;if (_month == 13) {++_year;_month = 1;}}return *this;
}//日期+天数 d+100是返回结果,d本身不改变
Date Date::operator+(int day) {//利用临时对象Date tmp = *this;tmp += day;return tmp;
}//日期-=天数 d1-100
Date& Date::operator-=(int day) {//-=负数-> +=正数if (day < 0) {return *this += -day;}//先减掉天数,若天数<=0 就继续借上个月的天数_day -= day;while (_day <= 0) {--_month;if (_month == 0) {_month = 12;--_year;}_day += getMonthDay(_year, _month);//借上个月}return *this;
}
Date Date::operator-(int day) {Date tmp = *this;tmp -= day;return tmp;
}//++d, 返回改变后
Date& Date::operator++() {return *this += 1;
}
//d++,返回改变前
Date Date::operator++(int) {Date tmp = *this;*this += 1;return tmp;
}//operator--
Date& Date::operator--() {return *this -= 1;
}
Date Date::operator--(int) {Date tmp = *this;*this -= 1;return tmp;
}//
//		2022-7-23   2003-4-10
//		计算2003的1月1日到2022年1月1日的差距 diff1
//		再计算处4-10和7-23分别是这一年的第几天,计算差值 diff2
//		两个差值相加即可//日期-日期 
int Date::operator-(const Date& d) {//计算 年份之间差多少天//先假设大的年份是 *this的年份int max = _year; //大的年份int min = d._year; //小的年份if (_year < d._year) {max = d._year;min = _year;}//计算 [min,max]之间的 整年中的闰年个数   整年范围: [min+1,max-1]int diff1 = (max - min) * 365 + getLeapNum(min+1,max-1);  //基础年数+闰年个数(闰年多1天)//计算分别是本年的第几天int diff2 = 0;int day1 = _day;for (int i = 1; i < _month; ++i) {day1 += getMonthDay(_year, i);}int day2 = d._day;for (int i = 1; i < d._month; ++i) {day2 += getMonthDay(d._year, i);}//diff2计算的是 *this和d 在这一年中 分别是第几天的差距,是 *this-ddiff2 = day1 - day2;//diff1计算的是 大年份比小年份差多少天,但目标要计算*this - d,如果d的年份大,要变一下符号。if (max == d._year) {diff1 *= -1;}return diff1 + diff2;
}//周几
string Date::DayofWeek() {//计算1.1.1到现在差多少天, 1.1.1默认周1static string weeks[] = { "周一","周二","周三","周四","周五","周六","周天" };//0对应周一 公园1,1,1是周1int n = *this - Date(1, 1, 1);int weekday = 1;	//逆推1,1,1是周2weekday += n;return weeks[weekday%7];
}

测试代码

//test.cpp
//测试日期比较大小
void test_Date1()
{Date d1;Date d2(2022, 7, 15);cout << (d1 == d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 < d2) << endl;}//测试+= 
void test_Date2()
{Date d1(2022, 7, 23);Date d2(d1);d1 += 86;d1 += 453;d1 += 4000;Date d3 = d2 + 86;d1 += -4000;d1 += -453;d1 += -86;}//测试 -=
void test_Date3()
{Date d1(2022, 7, 23);d1 -= 86;d1 -= 453;d1 -= 4000;
}//测试 ++ 和 --
void test_Date4()
{Date d1(2022, 7, 23);++d1;--d1;Date d2 = d1 + 1;
}//测试日期 - 日期
void test_Date5()
{Date d1(2022, 7, 23);Date d2(2022, 5, 5);Date d3(2022, 8, 15);Date d4(2020, 3, 25);Date d5(2025, 12, 25);cout << (d2 - d1) << endl;cout << (d3 - d1) << endl;cout << (d4 - d1) << endl;cout << (d5 - d1) << endl;}//测试 << >>
void test_Date6()
{Date d1(2024, 11, 13);cout << d1 << endl;Date d2;cin >> d2;cout << d1 << d2 << endl;
}//测试周几
void test_Date7()
{Date d1(2024,11, 13);cout << d1.DayOfWeek() << endl;
}
int main()
{//test_Date1();//test_Date2();//test_Date3();//test_Date4();//test_Date5();//test_Date6();test_Date7();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

集合类源码浅析のJDK1.8ConcurrentHashMap(上篇)

文章目录 前言一、概述二、CHM的属性1、属性 三、新增方法1、put2、initTable 四、分段计数1、addCount2、fullAddCount3、sumCount 总结 前言 本篇是JDK1.8的ConcurrentHashMap源码个人学习笔记&#xff0c;ConcurrentHashMap&#xff08;笔记中简称CHM&#xff09;是一种线程…

Linux权限和开发工具(3)

文章目录 1. 简单理解版本控制器Git1. 如何理解版本控制 2. Git的操作2.1 Git安装2.2 Git提交身份2.3 Git提交命令2.4 Git版本管理2.5 Git下的同步 3. gdb命令3.1解决gdb的难用问题3.2 gdb/cgdb的使用 1. 简单理解版本控制器Git 1. 如何理解版本控制 我们在做项目的时候可能会…

抓包工具WireShark使用记录

目录 网卡选择&#xff1a; 抓包流程&#xff1a; 捕获过滤器 常用捕获过滤器&#xff1a; 抓包数据的显示 显示过滤器&#xff1a; 常用的显示过滤器&#xff1a; 实际工作中&#xff0c;在平台对接&#xff0c;设备对接等常常需要调试接口&#xff0c;PostMan虽然可以进…

腾讯云双十一重磅福利----下一代CDN-EdgeOne

&#x1f34b;引言 随着全球互联网的快速发展和网络安全威胁的不断升级&#xff0c;传统的内容分发网络&#xff08;CDN&#xff09;已逐渐无法满足高效、安全、灵活的需求。腾讯云的下一代CDN产品—EdgeOne应运而生&#xff0c;凭借其全球化边缘节点架构&#xff0c;为客户提供…

Unity Coroutine

调用函数时&#xff0c;函数将运行到完成状态&#xff0c;然后返回。这实际上意味着在函数中发生的任何动作都必须在单帧更新内发生&#xff1b;函数调用不能用于包含程序性动画或随时间推移的一系列事件。例如&#xff0c;假设需要逐渐减少对象的 Alpha&#xff08;不透明度&a…

qt QGraphicsProxyWidget详解

1. 概述 QGraphicsProxyWidget 类是 Qt 图形视图框架中的一个关键类&#xff0c;它允许 QWidget 组件被嵌入到 QGraphicsScene 中。QGraphicsProxyWidget 作为一个代理&#xff0c;它在 QGraphicsScene 和 QWidget 之间建立了桥梁&#xff0c;使得 QWidget 可以在 QGraphicsVi…

【数据集】GPM IMERG Daily Precipitation Dataset

目录 数据集概述时空分辨率:数据下载参考数据集概述 Global Precipitation Measurement (GPM) IMERG Daily Precipitation Dataset 简介 Global Precipitation Measurement (GPM) 是由美国国家航空航天局(NASA)和日本宇宙航空研究开发机构(JAXA)联合发起的一项全球降水观…

MySQL 迁移 dm

参考链接 此处为语雀内容卡片&#xff0c;点击链接查看&#xff1a;MySQL 5.7.27 迁移 DM 8 语雀 迁移前准备 以下中的命名&#xff0c;密码都是可修改的&#xff0c;这里给出的就只是一个例子 创建表空间 # 创建表空间名为 dbTest&#xff0c;路径为 Z:\fei\data\dm\dbT…

新版IJidea 如何打开数据库窗口(2024.2.4 版)(连接数据库)

新版IJidea 2024.2.4 如何打开数据库窗口&#xff1f; 方式&#xff1a;使用插件&#xff0c;Database Navigator 1.安装插件&#xff0c;步骤如下&#xff1a; 打开 Settings/Preferences 对话框&#xff08;快捷键 CtrlAltS&#xff09;。前往 Plugins 菜单项。在搜索框中…

MySQL:left join后用on与where的区别

一、前言 前几天项目中&#xff0c;写SQL时本想通过 A left B join on and 后面的条件来使查出的两条记录变成一条&#xff0c;奈何发现还是有两条。在此记录一下&#xff0c;on与where的区别。 二、ON 原始数据展示 SELECT t1.*,t2.* FROM t_test_staff t1 left join t_te…

Spark 核心概念与宽窄依赖的详细解析

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

【树莓派raspberrypi烧录Ubuntu远程桌面登入树莓派】

提示&#xff1a;本文利用的是Ubuntu主机和树莓派4B开发板&#xff0c;示例仅供参考 文章目录 一、树莓派系统安装下载前准备工作下载安装树莓派的官方烧录软件imagerimager的使用方法 二、主机与树莓SSH连接查看数梅派IP地址建立ssh连接更新树莓派源地址 三、主机端远程桌面配…

MySQL数据库专栏(四)MySQL数据库链接操作C#篇

摘要 本篇文章主要介绍C#链接MySQL数据库的接口介绍&#xff0c;使用实例及注意事项&#xff0c;辅助类的封装及调用实例&#xff0c;可以直接移植到项目里面使用。 目录 1、添加引用 2、接口介绍 2.1、MySqlConnection 2.2、MySqlCommand 2.3、MySqlDataReader…

百度世界2024:AI应用的浪潮时刻

百度AI公式&#xff1a;“技术商业社会”。 作者|金豫 编辑|杨舟 互联网行业正迈入增长瓶颈期&#xff0c;这一点从主要科技巨头&#xff0c;如Meta、Alphabet、腾讯等近年来的表现中可见端倪&#xff1a;广告收入增速放缓&#xff0c;市场渗透率接近饱和。 单纯依赖流量获取…

Linux 通过nmcli配置网络并配置bond(网卡绑定)

Linux 通过nmcli配置网络并配置bond Linux 通过nmcli配置网络并配置bond1. 什么是 Bond 网卡绑定2. Bond 网卡绑定的常见模式3. 通过nmcli配置网络并做网卡绑定 Linux 通过nmcli配置网络并配置bond 1. 什么是 Bond 网卡绑定 Bond 网卡绑定&#xff08;或 NIC Bonding&#xff…

【Stable Diffusion - Ai】小白入门必看(想控制AI的绘画结果?ControlNet 预处理篇)!真材实料!不卖课!!!

【Stable Diffusion - Ai】小白入门必看&#xff08;想控制AI的绘画结果&#xff1f;ControlNet 预处理篇&#xff09;&#xff01;真材实料&#xff01;不卖课&#xff01;&#xff01;&#xff01; 对于ControlNet来说&#xff0c;很多人都会感觉到陌生&#xff1b;这个插件…

几何合理的分片段感知的3D分子生成 FragGen - 评测

FragGen 来源于 2024 年 3 月 25 日 预印本的文章&#xff0c;文章题目是 Deep Geometry Handling and Fragment-wise Molecular 3D Graph Generation&#xff0c; 作者是 Odin Zhang&#xff0c;侯廷军&#xff0c;浙江大学药学院。FragGen 是一个基于分子片段的 3D 分子生成模…

【设计模式系列】享元模式(十五)

目录 一、什么是享元模式 二、享元模式的角色 三、享元模式的典型应用场景 四、享元模式在ThreadPoolExecutor中的应用 1. 享元对象&#xff08;Flyweight&#xff09;- 工作线程&#xff08;Worker&#xff09; 2. 享元工厂&#xff08;Flyweight Factory&#xff09;- …

为什么分布式光伏规模是6MW为界点

安科瑞 华楠 近日&#xff0c;能源局发布定义分布式光伏6MW及以上的光伏电站必须自发自用&#xff0c;自行消纳。多省能源局规定大于6MW的电站必须按集中式管理&#xff0c;另外大于6MW&#xff08;包含&#xff09;要省级审批&#xff0c;小于则由市级审批&#xff0c;10kV线…

RDD 算子全面解析:从基础到进阶与面试要点

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…