diff --git a/Libraries/LibCore/DateTime.cpp b/Libraries/LibCore/DateTime.cpp index 1836c2d6a7..dac7c97599 100644 --- a/Libraries/LibCore/DateTime.cpp +++ b/Libraries/LibCore/DateTime.cpp @@ -36,6 +36,22 @@ DateTime DateTime::now() return from_timestamp(time(nullptr)); } +DateTime DateTime::create(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute, unsigned second) +{ + DateTime dt; + dt.m_year = year; + dt.m_month = month; + dt.m_day = day; + dt.m_hour = hour; + dt.m_minute = minute; + dt.m_second = second; + + struct tm tm = { (int)second, (int)minute, (int)hour, (int)day, (int)month, (int)year, (int)dt.weekday(), (int)dt.day_of_year(), -1 }; + dt.m_timestamp = mktime(&tm); + + return dt; +} + DateTime DateTime::from_timestamp(time_t timestamp) { struct tm tm; @@ -51,6 +67,55 @@ DateTime DateTime::from_timestamp(time_t timestamp) return dt; } +unsigned DateTime::weekday() const +{ + int target_year = m_year; + static const int seek_table[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; + if (m_month < 3) + --target_year; + + return (target_year + target_year / 4 - target_year / 100 + target_year / 400 + seek_table[m_month - 1] + m_day) % 7; +} + +unsigned DateTime::days_in_month() const +{ + bool is_long_month = (m_month == 1 || m_month == 3 || m_month == 5 || m_month == 7 || m_month == 8 || m_month == 10 || m_month == 12); + + if (m_month == 2) + return is_leap_year() ? 29 : 28; + + return is_long_month ? 31 : 30; +} + +unsigned DateTime::day_of_year() const +{ + static const int seek_table[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int day_of_year = seek_table[m_month - 1] + m_day; + + if (is_leap_year() && m_month > 3) + day_of_year++; + + return day_of_year - 1; +} + +bool DateTime::is_leap_year() const +{ + return ((m_year % 400 == 0) || (m_year % 4 == 0 && m_year % 100 != 0)); +} + +void DateTime::set_time(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute, unsigned second) +{ + m_year = year; + m_month = month; + m_day = day; + m_hour = hour; + m_minute = minute; + m_second = second; + + struct tm tm = { (int)second, (int)minute, (int)hour, (int)day, (int)month, (int)year, (int)weekday(), (int)day_of_year(), -1 }; + m_timestamp = mktime(&tm); +} + String DateTime::to_string(const String& format) const { diff --git a/Libraries/LibCore/DateTime.h b/Libraries/LibCore/DateTime.h index 56a9b17680..4409b42b07 100644 --- a/Libraries/LibCore/DateTime.h +++ b/Libraries/LibCore/DateTime.h @@ -42,9 +42,15 @@ public: unsigned hour() const { return m_hour; } unsigned minute() const { return m_minute; } unsigned second() const { return m_second; } + unsigned weekday() const; + unsigned days_in_month() const; + unsigned day_of_year() const; + bool is_leap_year() const; + void set_time(unsigned year, unsigned month = 1, unsigned day = 0, unsigned hour = 0, unsigned minute = 0, unsigned second = 0); String to_string(const String& format = "%Y-%m-%d %H:%M:%S") const; + static DateTime create(unsigned year, unsigned month = 1, unsigned day = 0, unsigned hour = 0, unsigned minute = 0, unsigned second = 0); static DateTime now(); static DateTime from_timestamp(time_t); diff --git a/Userland/cal.cpp b/Userland/cal.cpp index 8329645a10..4f14a33ba6 100644 --- a/Userland/cal.cpp +++ b/Userland/cal.cpp @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -43,26 +44,6 @@ int target_day; int current_year; int current_month; -int day_of_week(int day, int month, int year) -{ - static const int seek_table[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; - if (month < 3) - --year; - - return (year + year / 4 - year / 100 + year / 400 + seek_table[month - 1] + day) % 7; -} - -int get_number_of_days(int month, int year) -{ - bool is_leap_year = ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)); - bool is_long_month = (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12); - - if (month == 2) - return is_leap_year ? 29 : 28; - - return is_long_month ? 31 : 30; -} - void append_to_print(char* buffer, int row, int column, char* text) { int starting_point = (line_width * row) + (column * column_width); @@ -84,10 +65,10 @@ void insert_month_to_print(int column, int month, int year) sprintf(temp_buffer, "Su Mo Tu We Th Fr Sa"); append_to_print(print_buffer, printing_row, printing_column, temp_buffer); printing_row++; - int day_to_print = 1; - int first_day_of_week_for_month = day_of_week(1, month, year); - int days_in_the_month = get_number_of_days(month, year); + auto date_time = Core::DateTime::create(year, month, 1); + int first_day_of_week_for_month = date_time.weekday(); + int days_in_the_month = date_time.days_in_month(); int last_written_chars = 0; for (int i = 1; day_to_print <= days_in_the_month; ++i) { if (i - 1 < first_day_of_week_for_month) {