A Date class represents a calendar date with a year, month, and day of the month. It hides those implementation details while exposing date access, formatting, comparison, and arithmetic operations. section 5.3
Date arithmetic must handle Gregorian calendar rules, including month lengths and leap years. A day-by-day implementation works but performs expensive loops and repeatedly creates Date objects. section 5.3 section 5.3.1
Three implementations show how representation affects performance:
- Iteration 1 stores year, month, and day, then implements add_days() and days_from() by repeatedly calling next_date() or previous_date(). section 5.3.1
- Iteration 2 stores a private Julian day number, making addition and distance calculations direct integer operations, but converting back to year, month, and day remains expensive. section 5.3.2
- Iteration 3 stores both representations and tracks validity with Boolean flags, converting only when access or arithmetic requires synchronized data. section 5.3.3
Arithmetic test
For date1 = 9/2/2025 and date2 = 4/3/2027, days_from() returns 578; adding that count to date1 produces date2. The test demonstrates correct behavior, while the first implementation performs the calculation inefficiently. section 5.3.1
Listing 5.7 (Program 5.4 DateArithmetic-3): Date.h (efficient hybrid version)
#include <set>
using namespace std;
class Date
{
public:
Date(const int y, const int m, const int d)
: year(y), month(m), day(d), julian(0),
ymd_valid(true), julian_valid(false) {} #1
int get_year();
int get_month();
int get_day();
Date add_days(const int n);
int days_from(Date& other);
void print();
private:
static const set<int> LONG_MONTHS;
static const int JANUARY = ...
...
Date(int j)
: year(2000), month(1), day(1), julian(j),
ymd_valid(false), julian_valid(true) {} #2
int year, month, day;
int julian;
bool ymd_valid; #3
bool julian_valid; #4
static int days_in_month(const int year, const int month);
static bool is_leap_year(const int year);
void validate_ymd(); #5
void validate_julian(); #6
static int to_julian(const int year, const int month,
const int day);
static void to_ymd(const int julian, int& year, int& month,
int& day);
};
#1 The values of year, month, and day are valid after the Date object is created, but the value of julian is not.
#2 The value of julian is valid after the Date object is created, but the values of year, month, and day are not.
#3 Are values of the trio year, month, and day valid?
#4 Is the value of julian valid?
#5 Hidden helper function to make the values of the trio year, month, and day valid
#6 Hidden helper function to make the value of julian valid.
The efficient hybrid declaration makes representation hiding, cached validity, and lazy evaluation visible in a compact C++ example. section 5.3.3
