Files
2026-06-09 02:22:28 +08:00

119 lines
3.6 KiB
C++

#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
#include <sstream>
#include <cstdlib>
// 判断闰年
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 获取某个月的天数
int daysInMonth(int year, int month) {
if (month == 2) {
return isLeapYear(year) ? 29 : 28;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
}
return 31;
}
// 获取某年某月1号是星期几 (0 = Sunday, 1 = Monday, ..., 6 = Saturday)
int getFirstDayOfWeek(int year, int month) {
std::tm timeInfo = {0};
timeInfo.tm_year = year - 1900;
timeInfo.tm_mon = month - 1;
timeInfo.tm_mday = 1;
std::mktime(&timeInfo);
return timeInfo.tm_wday; // 0=周日, 6=周六
}
// 打印某年某月的日历
void printCalendar(int year, int month) {
// 月份名称数组
const char* monthNames[] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
// 获取当月天数及第一天星期几
int days = daysInMonth(year, month);
int startWeekday = getFirstDayOfWeek(year, month); // 0=周日
// 打印标题(居中显示,总宽度约20个字符)
std::cout << "\n " << monthNames[month - 1] << " " << year << "\n";
std::cout << "Su Mo Tu We Th Fr Sa\n";
// 打印日历网格(6行×7列 = 42格,保证完整)
int dayCounter = 1;
for (int i = 0; i < 42; ++i) {
if (i < startWeekday) {
// 月初前的空白格子
std::cout << " ";
} else if (dayCounter <= days) {
// 正常日期:右对齐占2位,后跟一个空格
std::cout << std::setw(2) << dayCounter << " ";
++dayCounter;
} else {
// 月末后的空白格子
std::cout << " ";
}
// 每7个格子换行
if (i % 7 == 6) {
std::cout << "\n";
}
}
std::cout << std::endl;
}
// 从字符串解析 "yyyy-mm-dd" 格式,成功返回true,并将year, month, day填入
bool parseDate(const std::string& dateStr, int& year, int& month, int& day) {
std::istringstream iss(dateStr);
char dash1, dash2;
if (iss >> year >> dash1 >> month >> dash2 >> day && dash1 == '-' && dash2 == '-') {
// 基础范围检查
if (year >= 1 && month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth(year, month)) {
return true;
}
}
return false;
}
// 获取当前系统时间的年份和月份
void getCurrentYearMonth(int& year, int& month) {
std::time_t t = std::time(nullptr);
std::tm* now = std::localtime(&t);
year = now->tm_year + 1900;
month = now->tm_mon + 1;
}
int main(int argc, char* argv[]) {
int year, month;
if (argc == 2) {
// 提供了日期参数,尝试解析
std::string dateArg = argv[1];
int day; // 解析出的日无需使用,仅用于校验
if (parseDate(dateArg, year, month, day)) {
printCalendar(year, month);
} else {
std::cerr << "错误:无效的日期格式或非法日期。请使用 yyyy-mm-dd 格式。\n";
std::cerr << "示例: " << argv[0] << " 2024-12-25\n";
return 1;
}
} else if (argc == 1) {
// 无参数,显示当前月份的日历
getCurrentYearMonth(year, month);
printCalendar(year, month);
} else {
std::cerr << "用法: " << argv[0] << " [yyyy-mm-dd]\n";
std::cerr << "若无参数,则显示当前月份的日历。\n";
return 1;
}
return 0;
}