02 日期类

02 日期类


作者:abnb250/山中鹤鸣
博客:https://www.cnblogs.com/abnb250
交流群:1062464078
点击返回目录



前情提要

这一节实现一个 Date 类,包含闰年判断、日期合法性校验、addday/subday 加减天数、比较与 YYYY-MM-DD 格式化输出。
注释版主要盯三处:
构造时非法日期直接归一到 2000-01-01,是为了维持类不变式;
subday 的 while(d <= 0) 不能用 < 0,d0 也是非法日期;
借位时必须先修正月份再取当月天数,否则 m
0 时 getdom 返回 0,d 不增,死循环。



代码(加注释版)

注释解释了两种场景:

  1. 代码有反直觉痕迹,自然写法就在旁边。
  2. 代码看起来自然,但背后有隐形决策。

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;
}








posted @ 2026-11-01 17:35  abnb250  阅读(3)  评论(0)    收藏  举报