In lịch đầy đủ của một năm cho trước. Tính ngày trong tháng (tháng 2 năm nhuận 29 ngày), ngày đầu tuần của 1/1 năm đó (Zeller congruence). In 12 tháng theo định dạng bảng.
Thuật toán ngày trong tuần
Công thức Zeller: dayOfWeek = (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7. Với mảng t[] = {0,3,2,5,0,3,5,1,4,6,2,4}. Năm nhuận: chia 400 hoặc (chia 4 và không chia 100).
Ví dụ minh họa
#include <iostream>
#include <iomanip>
using namespace std;
int dayOfWeek(int d, int m, int y) {
static int t[] = {0,3,2,5,0,3,5,1,4,6,2,4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
string monthName(int m) {
string names[] = {"January","February","March","April","May","June",
"July","August","September","October","November","December"};
return names[m];
}
int daysInMonth(int m, int y) {
if (m==1) {
bool leap = (y%400==0) || (y%4==0 && y%100!=0);
return leap ? 29 : 28;
}
if (m==3||m==5||m==8||m==10) return 30;
return 31;
}
void printCalendar(int year) {
cout << "\t\t\t Calendar - Year " << year << '\n';
int curr = dayOfWeek(1, 1, year);
for (int m = 0; m < 12; m++) {
int days = daysInMonth(m, year);
cout << "\n\t\t ----X----" << monthName(m) << "----X----\n";
cout << " Sun Mon Tue Wed Thu Fri Sat\n";
for (int i = 0; i < curr; i++) cout << " ";
for (int d = 1; d <= days; d++) {
cout << setw(4) << d;
if (++curr > 6) { curr = 0; cout << '\n'; }
}
if (curr) cout << '\n';
}
}
int main() {
printCalendar(2019);
return 0;
}
Kết quả
Calendar - Year 2019
----X----January----X----
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
... (các tháng còn lại)