02 日期类
02 日期类
作者:abnb250/山中鹤鸣
博客:https://www.cnblogs.com/abnb250
交流群:1062464078
点击返回目录
前情提要
这一节实现一个 Date 类,包含闰年判断、日期合法性校验、addday/subday 加减天数、比较与 YYYY-MM-DD 格式化输出。
注释版主要盯三处:
构造时非法日期直接归一到 2000-01-01,是为了维持类不变式;
subday 的 while(d <= 0) 不能用 < 0,d0 也是非法日期;
借位时必须先修正月份再取当月天数,否则 m0 时 getdom 返回 0,d 不增,死循环。
代码(加注释版)
注释解释了两种场景:
- 代码有反直觉痕迹,自然写法就在旁边。
- 代码看起来自然,但背后有隐形决策。
Date.h
#ifndef DATE_H
#define DATE_H
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
class Date{
private:
int year;
int month;
int day;
bool isok() const;
public:
Date(int y = 2000, int m = 1, int d = 1): year(y), month(m), day(d) {
// 不能省略校验直接保存非法日期,getdate/addday 等按合法日期假设工作,会输出非法字符串或归一出意外结果
if(!isok()){year = 2000; month = 1; day = 1;}
}
static bool isleap(int y);
Date addday(int num) const;
Date subday(int num) const;
int getday() const;
int getyear() const;
int getmonth() const;
std::string getdate() const;
friend std::ostream& operator<<(std::ostream& os, const Date& a);
bool operator==(const Date& b) const;
bool operator!=(const Date& b) const;
bool operator<(const Date& b) const;
};
#endif
Date.cpp
#include "date.h"
bool Date::isleap(int y){
if(y % 400 == 0 || (y % 4 == 0 && y % 100 !=0)) return true;
return false;
}
int getdom(int yea, int mon){
int md[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(mon == 2){
if(Date::isleap(yea)) return 29;
return 28;
}
return md[mon];
}
bool Date::isok() const {
if(day < 1 || month < 1 || month > 12) {
std::cout << "date is error" << '\n';
return false;
}
int dom = getdom(year, month);
if(day > dom ){
std::cout << "date is error" << '\n';
return false;
}
return true;
}
Date Date::addday(int num) const{
if(num < 0) return subday(-num);
int y = year;
int m = month;
int d = day+num;
while(d > getdom(y, m)){
int dom = getdom(y,m);
d -= dom;
m += 1;
if(m > 12){
m = 1;
y += 1;
}
}
Date res(y, m, d);
return res;
}
Date Date::subday(int num) const{
if(num < 0) return addday(-num);
int y = year;
int m = month;
int d = day-num;
// 不能改成 d < 0,d==0 时是非法日期,需要借到上月最后一天
while(d <= 0){
m -= 1;
if(m < 1){
m = 12;
y -= 1;
}
// 不能先 getdom 再减月/修正 m<1:会加到当月天数;m=0 时 getdom 返回 0,d 不增,死循环
int dom = getdom(y, m);
d += dom;
}
Date res(y, m, d);
return res;
}
int Date::getyear() const{
return year;
}
int Date::getmonth() const{
return month;
}
int Date::getday() const{
return day;
}
std::string Date::getdate() const{
using namespace std;
string ye = to_string(year);
string mo = to_string(month);
string da = to_string(day);
while(mo.size() < 2){
mo = "0" + mo;
}
while(da.size() < 2){
da = "0" + da;
}
string res;
res = ye + "-" + mo + "-" + da;
return res;
}
std::ostream& operator<<(std::ostream& os, const Date& a){
os << a.getdate();
return os;
}
bool Date::operator==(const Date& b) const{
if(year != b.year) return false;
if(month != b.month) return false;
if(day != b.day) return false;
return true;
}
bool Date::operator!=(const Date& b) const{
if(*this == b) return false;
return true;
}
bool Date::operator<(const Date& b) const{
if(*this == b) return false;
if(year < b.year) return true;
else if(year == b.year){
if(month < b.month) return true;
else if(month == b.month){
if(day < b.day) return true;
else return false;
}
}
return false;
}
/*
我要这天再遮不住我眼,我要这地再埋不住我心。
交流群:1062464078
*/

浙公网安备 33010602011771号