119 lines
3.6 KiB
C++
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;
|
|
} |