// class_date.h (c) 1997-2002 Kari Laitinen // http://www.naturalprogramming.com // 2.10.1997 file created. // 15.05.2001 include guards added. // 15.10.2001 Function get_week_number was rewritten. // 13.08.2002 This file does not include iomanip.h any more. // This file contains the definition for class Date and // its member functions. #ifndef CLASS_DATE_H // prohibiting multiple inclusions #define CLASS_DATE_H class Date { protected: int this_day ; int this_month ; int this_year ; char date_print_format ; public: Date( int given_day = 1, int given_month = 1, int given_year = 1970, char print_format = 'E' ) ; Date( char date_as_string[] ) ; int day() { return this_day ; } int month() { return this_month ; } int year() { return this_year ; } char get_date_print_format() { return date_print_format ; } bool is_last_day_of_month() ; bool this_is_a_leap_year() ; bool is_within_dates( Date& earlier_date, Date& later_date ) ; int index_for_day_of_week() ; void print_day_of_week( ostream& output_stream ) ; void increment() ; void decrement() ; void get_distance_to( Date& another_date, int& years_of_distance, int& months_of_distance, int& days_of_distance ) ; int get_week_number() ; bool operator==( Date& another_date ) ; bool operator!=( Date& another_date ) ; bool operator< ( Date& another_date ) ; bool operator> ( Date& another_date ) ; friend ostream& operator<<( ostream& output_stream, Date& date_to_output ) ; } ; Date::Date( int given_day, int given_month, int given_year, char given_print_format ) { this_day = given_day ; this_month = given_month ; this_year = given_year ; date_print_format = given_print_format ; } Date::Date( char date_as_string[] ) { // This constructor accepts date strings in two formats: // // MM/DD/YYYY is the American format. // DD.MM.YYYY is the format used in Europe. // // Member variable date_print_format will be set either // to value 'A' or 'E'. This value will be used to select // correct print format when this date object is printed. if ( date_as_string[ 2 ] == '/' ) { date_print_format = 'A' ; // American format this_day = ( date_as_string[ 3 ] & 0x0F ) * 10 + ( date_as_string[ 4 ] & 0x0F ) ; this_month = ( date_as_string[ 0 ] & 0x0F ) * 10 + ( date_as_string[ 1 ] & 0x0F ) ; } else { date_print_format = 'E' ; // European format this_day = ( date_as_string[ 0 ] & 0x0F ) * 10 + ( date_as_string[ 1 ] & 0x0F ) ; this_month = ( date_as_string[ 3 ] & 0x0F ) * 10 + ( date_as_string[ 4 ] & 0x0F ) ; } this_year = ( date_as_string[ 6 ] & 0x0F ) * 1000 + ( date_as_string[ 7 ] & 0x0F ) * 100 + ( date_as_string[ 8 ] & 0x0F ) * 10 + ( date_as_string[ 9 ] & 0x0F ) ; } bool Date::is_last_day_of_month() { bool it_is_last_day_of_month = false ; if ( this_day > 27 ) { if ( this_day == 31 ) { it_is_last_day_of_month = true ; } else if ( ( this_day == 30 ) && ( this_month == 2 || this_month == 4 || this_month == 6 || this_month == 9 || this_month == 11 ) ) { it_is_last_day_of_month = true ; } else if ( this_day == 29 && this_month == 2 ) { it_is_last_day_of_month = true ; } else if ( this_day == 28 && this_month == 2 && ! this_is_a_leap_year() ) { it_is_last_day_of_month = true ; } } return it_is_last_day_of_month ; } bool Date::this_is_a_leap_year() { bool return_code = false ; if ( this_year % 4 == 0 ) { // Years which are equally divisible by 4 and which // are not full centuries are leap years. Centuries // equally divisible by 4 are, however, leap years. if ( this_year % 100 == 0 ) { int century = this_year / 100 ; if ( century % 4 == 0 ) { return_code = true ; } } else { return_code = true ; } } return return_code ; } bool Date::is_within_dates( Date& earlier_date, Date& later_date ) { return (( *this == earlier_date ) || ( *this == later_date ) || ( *this > earlier_date && *this < later_date ) ) ; } int Date::index_for_day_of_week() { // day_index will get a value in the range from 0 to 6, // 0 meaning Monday and 6 meaning Sunday. int day_index = 0 ; Date known_date( 6, 10, 1997 ) ; // Oct. 6, 1997 is Monday. if ( *this < known_date ) { while ( *this != known_date ) { if ( day_index > 0 ) { day_index -- ; } else { day_index = 6 ; } known_date.decrement() ; } } else { while ( *this != known_date ) { if ( day_index < 6 ) { day_index ++ ; } else { day_index = 0 ; } known_date.increment() ; } } return day_index ; } void Date::print_day_of_week( ostream& output_stream ) { char* days_of_week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" } ; output_stream << days_of_week[ index_for_day_of_week() ] ; } void Date::increment() { if ( is_last_day_of_month() ) { this_day = 1 ; if ( this_month < 12 ) { this_month ++ ; } else { this_month = 1 ; this_year ++ ; } } else { this_day ++ ; } } void Date::decrement() { if ( this_day > 1 ) { this_day -- ; } else { if ( this_month == 5 || this_month == 7 || this_month == 10 || this_month == 12 ) { this_day = 30 ; this_month -- ; } else if ( this_month == 2 || this_month == 4 || this_month == 6 || this_month == 8 || this_month == 9 || this_month == 11 ) { this_day = 31 ; this_month -- ; } else if ( this_month == 1 ) { this_day = 31 ; this_month = 12 ; this_year -- ; } else if ( this_month == 3 ) { this_month = 2 ; if ( this_is_a_leap_year() ) { this_day = 29 ; } else { this_day = 28 ; } } } } void Date::get_distance_to( Date& another_date, int& years_of_distance, int& months_of_distance, int& days_of_distance ) { Date start_date ; Date end_date ; int start_day, end_day ; if ( *this < another_date ) { start_date = *this ; end_date = another_date ; } else { start_date = another_date ; end_date = *this ; } // We will suppose that day 30 is the last day of every // month. This way we minimize calculation errors. if ( start_date.is_last_day_of_month() || ( start_date.day() == 28 && start_date.month() == 2 ) ) { start_day = 30 ; } else { start_day = start_date.day() ; } if ( end_date.is_last_day_of_month() || ( end_date.day() == 28 && end_date.month() == 2 ) ) { end_day = 30 ; } else { end_day = end_date.day() ; } years_of_distance = end_date.year() - start_date.year() ; months_of_distance = end_date.month() - start_date.month() ; days_of_distance = end_day - start_day ; if ( days_of_distance < 0 ) { months_of_distance -- ; days_of_distance = days_of_distance + 30 ; } if ( months_of_distance < 0 ) { years_of_distance -- ; months_of_distance = months_of_distance + 12 ; } } int Date::get_week_number() { // January 1, 1883 was a Monday with week number 1. // January 1, 1990 was a Monday with week number 1. Date date_to_increment( 1, 1, 1883 ) ; int week_number = 1 ; int local_index_for_day_of_week = 0 ; // 0 means Monday while ( date_to_increment < *this ) { date_to_increment.increment() ; if ( local_index_for_day_of_week == 6 ) // 6 means Sunday { local_index_for_day_of_week = 0 ; // back to Monday if ( week_number < 52 ) { week_number ++ ; } else if ( week_number == 52 ) { if ( date_to_increment.day() <= 28 && date_to_increment.month() == 12 ) { week_number = 53 ; } else { week_number = 1 ; } } else // must be week_number 53 { week_number = 1 ; } } else { local_index_for_day_of_week ++ ; } } return week_number ; } bool Date::operator==( Date& another_date ) { return ( this_day == another_date.this_day && this_month == another_date.this_month && this_year == another_date.this_year ) ; } bool Date::operator!=( Date& another_date ) { return ( this_day != another_date.this_day || this_month != another_date.this_month || this_year != another_date.this_year ) ; } bool Date::operator< ( Date& another_date ) { return ( ( this_year < another_date.this_year ) || ( ( this_year == another_date.this_year ) && ( this_month < another_date.this_month ) ) || ( ( this_year == another_date.this_year ) && ( this_month == another_date.this_month ) && ( this_day < another_date.this_day ) ) ) ; } bool Date::operator> ( Date& another_date ) { return ( ( this_year > another_date.this_year ) || ( ( this_year == another_date.this_year ) && ( this_month > another_date.this_month ) ) || ( ( this_year == another_date.this_year ) && ( this_month == another_date.this_month ) && ( this_day > another_date.this_day ) ) ) ; } ostream& operator<<( ostream& output_stream, Date& date_to_output ) { char day_as_string[] = "00" ; char month_as_string[] = "00" ; day_as_string[ 0 ] = 0x30 + date_to_output.this_day / 10 ; day_as_string[ 1 ] = 0x30 + date_to_output.this_day % 10 ; month_as_string[ 0 ] = 0x30 + date_to_output.this_month / 10 ; month_as_string[ 1 ] = 0x30 + date_to_output.this_month % 10 ; if ( date_to_output.date_print_format == 'A' ) { output_stream << month_as_string << "/" << day_as_string << "/" << date_to_output.this_year ; } else { output_stream << day_as_string << "." << month_as_string << "." << date_to_output.this_year ; } return output_stream ; } #endif // end of include guard