// class_date_x.h (c) 2001 Kari Laitinen // 13.11.2001 file created. // 13.11.2001 Last modification. /* This is an improved version of class_date.h This Date class is equipped with functions is_in_year_of is_in_month_of operator>> */ #ifndef CLASS_DATE_H // prohibiting multiple inclusions #define CLASS_DATE_H #include 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_in_year_of( Date& another_date ) ; bool is_in_month_of( Date& another_date ) ; 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 ) ; friend istream& operator>>( istream& input_stream, Date& input_date ) ; } ; 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_in_year_of( Date& another_date ) { return ( this_year == another_date.this_year ) ; } bool Date::is_in_month_of( Date& another_date ) { return ( this_year == another_date.this_year && this_month == another_date.this_month ) ; } 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 ) { output_stream << setfill( '0' ) << right ; if ( date_to_output.date_print_format == 'A' ) { output_stream << setw( 2 ) << date_to_output.this_month << "/" << setw( 2 ) << date_to_output.this_day << "/" << date_to_output.this_year ; } else { output_stream << setw( 2 ) << date_to_output.this_day << "." << setw( 2 ) << date_to_output.this_month << "." << date_to_output.this_year ; } return output_stream ; } istream& operator>>( istream& input_stream, Date& input_date ) { char input_date_as_string[ 30 ] ; input_stream >> input_date_as_string ; /* By creating a temporary_input_date we can make the constructor of this class to interpret the date string. The constructor takes care that the string is converted to an American or European date object in a correct manner. */ Date temporary_input_date( input_date_as_string ) ; input_date = temporary_input_date ; return input_stream ; } #endif // end of include guard