Skip to content

Commit 48489de

Browse files
committed
Added GetDifference function to Date class to get days, months and years of difference for issue #17.
1 parent 6942ad1 commit 48489de

File tree

2 files changed

+170
-2
lines changed

2 files changed

+170
-2
lines changed

Date.hpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ class Date
475475
return total_days;
476476
}
477477

478-
/// Get number of days between two dates for the same year.
478+
/// Get number of days between two dates for the same year in days.
479479
/// First date must be less or equal to second date.
480480
static size_type GetDifferenceInDays(day_type first_day,
481481
month_type first_month,
@@ -488,7 +488,7 @@ class Date
488488
return second_days_to_start - first_days_to_start;
489489
}
490490

491-
/// Get number of days between two dates.
491+
/// Get number of days between two dates in days.
492492
/// First date must be less or equal to second date.
493493
static size_type GetDifferenceInDays(day_type first_day,
494494
month_type first_month,
@@ -512,6 +512,43 @@ class Date
512512
return days;
513513
}
514514

515+
/// Get number of days, months and years between two dates.
516+
/// First date must be less or equal to second date.
517+
static void GetDifference(day_type first_day,
518+
month_type first_month,
519+
year_type first_year,
520+
day_type second_day,
521+
month_type second_month,
522+
year_type second_year,
523+
day_type& diff_days,
524+
month_type& diff_months,
525+
year_type& diff_years) noexcept
526+
{
527+
if (second_year > first_year)
528+
{
529+
bool const is_month_day_greater_equal = second_month > first_month ||
530+
((second_month == first_month) &&
531+
(second_day >= first_day));
532+
533+
diff_years = is_month_day_greater_equal ? second_year - first_year
534+
: second_year - first_year - 1;
535+
}
536+
else
537+
diff_years = 0;
538+
539+
if (second_month > first_month)
540+
diff_months = (second_day >= first_day) ? second_month - first_month
541+
: second_month - first_month - 1;
542+
else
543+
diff_months = (diff_years > 0) && (second_month != first_month) ?
544+
MONTHS_PER_YEAR + second_month - first_month : 0;
545+
546+
if (second_day >= first_day)
547+
diff_days = second_day - first_day;
548+
else
549+
diff_days = (GetDaysInMonth(first_month, first_year) - first_day) + second_day;
550+
}
551+
515552
static Date const& Min(Date const& first, Date const& second) noexcept
516553
{
517554
return first < second ? first : second;
@@ -753,6 +790,18 @@ class Date
753790
other.GetDay(), other.GetMonth(), other.GetYear());
754791
}
755792

793+
/// Get number of days, months and years between two dates.
794+
/// other date must be greater or equal to this date.
795+
void GetDifference(Date const& other,
796+
day_type& diff_days,
797+
month_type& diff_months,
798+
year_type& diff_years) const noexcept
799+
{
800+
GetDifference(GetDay(), GetMonth(), GetYear(),
801+
other.GetDay(), other.GetMonth(), other.GetYear(),
802+
diff_days, diff_months, diff_years);
803+
}
804+
756805
/// Set to the 1st of January for the current year.
757806
void SetStartOfYear() noexcept
758807
{

unit_tests/Date_tests.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,125 @@ TEST_MEMBER_FUNCTION(Date, GetDifferenceInDays, day_type_month_type_year_type_da
738738
CHECK_EQUAL(Date::GetDifferenceInDays(Date::DAYS_IN_DECEMBER, Date::DECEMBER, 2000U, Date::DAYS_IN_DECEMBER, Date::DECEMBER, 2003U), Date::GetDaysInYears(2001U, 2003U));
739739
}
740740

741+
TEST_MEMBER_FUNCTION(Date, GetDifference, day_type_month_type_year_type_day_type_month_type_year_type_day_type_ref_month_type_ref_year_type_ref)
742+
{
743+
TEST_OVERRIDE_ARGS("day_type, month_type, year_type, day_type, month_type, year_type, day_type&, month_type&, year_type&");
744+
745+
Date::day_type diff_days = 99;
746+
Date::month_type diff_months = 99;
747+
Date::year_type diff_years = 10000;
748+
749+
// Check minimum difference of 1 days over a year boundary.
750+
Date::GetDifference(Date::DAYS_IN_DECEMBER, Date::DECEMBER, 1999U, 1U, Date::JANUARY, 2000U, diff_days, diff_months, diff_years);
751+
CHECK_EQUAL(diff_days, 1);
752+
CHECK_EQUAL(diff_months, 0);
753+
CHECK_EQUAL(diff_years, 0);
754+
755+
// Check minimum difference of 1 days over a month boundary.
756+
diff_days = 99;
757+
diff_months = 99;
758+
diff_years = 10000;
759+
Date::GetDifference(Date::DAYS_IN_MARCH, Date::MARCH, 1999U, 1U, Date::APRIL, 1999U, diff_days, diff_months, diff_years);
760+
CHECK_EQUAL(diff_days, 1);
761+
CHECK_EQUAL(diff_months, 0);
762+
CHECK_EQUAL(diff_years, 0);
763+
764+
// Check minimum difference of 1 days over a non-leap month boundary.
765+
diff_days = 99;
766+
diff_months = 99;
767+
diff_years = 10000;
768+
Date::GetDifference(Date::DAYS_IN_FEBRUARY, Date::FEBRUARY, 1999U, 1U, Date::MARCH, 1999U, diff_days, diff_months, diff_years);
769+
CHECK_EQUAL(diff_days, 1);
770+
CHECK_EQUAL(diff_months, 0);
771+
CHECK_EQUAL(diff_years, 0);
772+
773+
// Check minimum difference of 1 days over a non-leap month boundary.
774+
diff_days = 99;
775+
diff_months = 99;
776+
diff_years = 10000;
777+
Date::GetDifference(Date::DAYS_IN_FEBRUARY, Date::FEBRUARY, 2020U, 1U, Date::MARCH, 2020U, diff_days, diff_months, diff_years);
778+
CHECK_EQUAL(diff_days, 2);
779+
CHECK_EQUAL(diff_months, 0);
780+
CHECK_EQUAL(diff_years, 0);
781+
782+
// Check first and last day in the same year.
783+
diff_days = 99;
784+
diff_months = 99;
785+
diff_years = 10000;
786+
Date::GetDifference(1U, Date::JANUARY, 2020U, Date::DAYS_IN_DECEMBER, Date::DECEMBER, 2020U, diff_days, diff_months, diff_years);
787+
CHECK_EQUAL(diff_days, Date::DAYS_IN_DECEMBER - 1);
788+
CHECK_EQUAL(diff_months, 11);
789+
CHECK_EQUAL(diff_years, 0);
790+
791+
// Check first and last day in the every month, including non-leap year and leap year.
792+
for (Date::year_type y = 2019U; y <= 2020U; ++y)
793+
for (Date::month_type m = Date::JANUARY; m <= Date::DECEMBER; ++m)
794+
{
795+
diff_days = 99;
796+
diff_months = 99;
797+
diff_years = 10000;
798+
Date::month_type days_in_month = Date::GetDaysInMonth(m, y);
799+
Date::GetDifference(1U, m, y, days_in_month, m, y, diff_days, diff_months, diff_years);
800+
CHECK_EQUAL(diff_days, days_in_month - 1);
801+
CHECK_EQUAL(diff_months, 0);
802+
CHECK_EQUAL(diff_years, 0);
803+
}
804+
805+
// Check 1 day over a year difference for non-leap year.
806+
diff_days = 99;
807+
diff_months = 99;
808+
diff_years = 10000;
809+
Date::GetDifference(1U, Date::JANUARY, 2019U, 2U, Date::JANUARY, 2020U, diff_days, diff_months, diff_years);
810+
CHECK_EQUAL(diff_days, 1);
811+
CHECK_EQUAL(diff_months, 0);
812+
CHECK_EQUAL(diff_years, 1);
813+
814+
// Check 1 day over a year difference for leap year.
815+
diff_days = 99;
816+
diff_months = 99;
817+
diff_years = 10000;
818+
Date::GetDifference(1U, Date::JANUARY, 2020U, 2U, Date::JANUARY, 2021U, diff_days, diff_months, diff_years);
819+
CHECK_EQUAL(diff_days, 1);
820+
CHECK_EQUAL(diff_months, 0);
821+
CHECK_EQUAL(diff_years, 1);
822+
823+
// Check 1 day and 1 month over a year difference for non-leap year.
824+
diff_days = 99;
825+
diff_months = 99;
826+
diff_years = 10000;
827+
Date::GetDifference(1U, Date::JANUARY, 2019U, 2U, Date::FEBRUARY, 2020U, diff_days, diff_months, diff_years);
828+
CHECK_EQUAL(diff_days, 1);
829+
CHECK_EQUAL(diff_months, 1);
830+
CHECK_EQUAL(diff_years, 1);
831+
832+
// Check 1 day and 1 month over a year difference for leap year.
833+
diff_days = 99;
834+
diff_months = 99;
835+
diff_years = 10000;
836+
Date::GetDifference(1U, Date::JANUARY, 2020U, 2U, Date::FEBRUARY, 2021U, diff_days, diff_months, diff_years);
837+
CHECK_EQUAL(diff_days, 1);
838+
CHECK_EQUAL(diff_months, 1);
839+
CHECK_EQUAL(diff_years, 1);
840+
841+
// Check 1 day and 2 month over 3 years difference for non-leap year.
842+
diff_days = 99;
843+
diff_months = 99;
844+
diff_years = 10000;
845+
Date::GetDifference(1U, Date::JANUARY, 2019U, 2U, Date::MARCH, 2022U, diff_days, diff_months, diff_years);
846+
CHECK_EQUAL(diff_days, 1);
847+
CHECK_EQUAL(diff_months, 2);
848+
CHECK_EQUAL(diff_years, 3);
849+
850+
// Check 1 day and 2 month over 3 years difference for leap year.
851+
diff_days = 99;
852+
diff_months = 99;
853+
diff_years = 10000;
854+
Date::GetDifference(1U, Date::JANUARY, 2020U, 2U, Date::MARCH, 2023U, diff_days, diff_months, diff_years);
855+
CHECK_EQUAL(diff_days, 1);
856+
CHECK_EQUAL(diff_months, 2);
857+
CHECK_EQUAL(diff_years, 3);
858+
}
859+
741860
TEST_MEMBER_FUNCTION(Date, GetPreviousDay, day_type_month_type_year_type)
742861
{
743862
TEST_OVERRIDE_ARGS("day_type, month_type, year_type");

0 commit comments

Comments
 (0)