首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 實作日期類別:完整驗證與日期運算教學

     編輯:程式設計疑難解答

前言

在 C++ 開發中,處理日期時間是常見需求。雖然標準庫提供了 chrono 與 C 風格的 time.h,但手寫一個日期類別能深入理解日期驗證、閏年計算與跨月跨年邏輯。本文將完整實作一個 Date 類別,包含初始化驗證、年月日增減運算,並處理閏年、大小月等邊界情況。

類別設計與資料成員

我們定義三個私有整數成員儲存日、月、年:

class Date {
private:
    int day, month, year;
public:
    void InitDate(int d, int m, int y);
    void AddYear(int y);
    void AddMonth(int m);
    void AddDay(int d);
};

初始化與有效性驗證

InitDate 需檢查年份範圍(-2000 ~ 3000)、月份(1~12)、日期是否符合該月天數(含閏年二月)。

bool IsLeapYear(int y) {
    return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}

int DaysInMonth(int m, int y) {
    static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    if (m == 2 && IsLeapYear(y)) return 29;
    return days[m-1];
}

void Date::InitDate(int d, int m, int y) {
    if (y < -2000 || y > 3000) throw std::invalid_argument("年份超出範圍");
    if (m < 1 || m > 12) throw std::invalid_argument("月份無效");
    int maxDay = DaysInMonth(m, y);
    if (d < 1 || d > maxDay) throw std::invalid_argument("日期無效");
    day = d; month = m; year = y;
}

年份增減:處理閏年 2/29

增加年份時,若原日期為 2 月 29 日且目標年非閏年,需調整為 2 月 28 日。

void Date::AddYear(int y) {
    year += y;
    if (month == 2 && day == 29 && !IsLeapYear(year)) {
        day = 28; // 非閏年無 2/29
    }
}

月份增減:處理大小月與跨年

月份增減可能跨年,且需調整日期不超過目標月天數(如 1/31 加一個月變 2/28 或 2/29)。

void Date::AddMonth(int m) {
    int totalMonth = year * 12 + (month - 1) + m;
    year = totalMonth / 12;
    month = totalMonth % 12 + 1;
    int maxDay = DaysInMonth(month, year);
    if (day > maxDay) day = maxDay;
}

日期增減:跨月、跨年、閏月

日期增減最複雜,需逐日遞增/遞減,或用「轉換為絕對天數」演算法。這裡示範逐日調整:

void Date::AddDay(int d) {
    if (d >= 0) {
        while (d--) {
            day++;
            if (day > DaysInMonth(month, year)) {
                day = 1;
                month++;
                if (month > 12) { month = 1; year++; }
            }
        }
    } else {
        while (d++) {
            day--;
            if (day == 0) {
                month--;
                if (month == 0) { month = 12; year--; }
                day = DaysInMonth(month, year);
            }
        }
    }
}

完整範例與測試

以下主程式示範各種邊界情況:

int main() {
    Date dt;
    dt.InitDate(29, 2, 2012); // 閏年 2/29
    dt.AddYear(1);            // 變 2013/2/28
    dt.InitDate(31, 1, 2014);
    dt.AddMonth(1);           // 變 2014/2/28
    dt.InitDate(31, 12, 2020);
    dt.AddDay(1);             // 變 2021/1/1
    return 0;
}

總結

自行實作日期類別能強化對曆法邏輯的掌握。實務上建議使用 std::chrono(C++20)或成熟庫(如 Howard Hinnant's date.h),但理解底層運作對除錯與效能調優大有裨益。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved