diff --git a/bindings/guile/gnc-optiondb.i b/bindings/guile/gnc-optiondb.i index 5d2cf7e0e7..29a7a9591a 100644 --- a/bindings/guile/gnc-optiondb.i +++ b/bindings/guile/gnc-optiondb.i @@ -591,6 +591,10 @@ gnc_option_test_book_destroy(QofBook* book) $1 = rdp; } +%typecheck(SWIG_TYPECHECK_INTEGER) RelativeDatePeriod { + $1 = scm_is_integer($input) || scm_is_symbol($input) ? 1 : 0; +} + %typemap(in) RelativeDatePeriodVec& (RelativeDatePeriodVec period_set) { for (SCM node = $input; !scm_is_null (node); node = scm_cdr (node)) diff --git a/libgnucash/engine/gnc-option-date.cpp b/libgnucash/engine/gnc-option-date.cpp index a370681b3a..d5c0e104c0 100644 --- a/libgnucash/engine/gnc-option-date.cpp +++ b/libgnucash/engine/gnc-option-date.cpp @@ -516,7 +516,7 @@ reldate_set_day_and_time( }; time64 -gnc_relative_date_to_time64(RelativeDatePeriod period) +gnc_relative_date_to_time64(RelativeDatePeriod period, time64 now_t) { if (period == RelativeDatePeriod::TODAY) return static_cast(GncDateTime()); @@ -525,10 +525,9 @@ gnc_relative_date_to_time64(RelativeDatePeriod period) if (period == RelativeDatePeriod::END_ACCOUNTING_PERIOD) return gnc_accounting_period_fiscal_end(); - GncDateTime now_t; if (period == RelativeDatePeriod::TODAY) - return static_cast(now_t); - auto now{static_cast(now_t)}; + return now_t; + auto now{static_cast(GncDateTime(now_t))}; struct tm acct_per = static_cast(GncDateTime(gnc_accounting_period_fiscal_start())); auto offset = reldate_offset(period); diff --git a/libgnucash/engine/gnc-option-date.hpp b/libgnucash/engine/gnc-option-date.hpp index 98dc0fac07..52dfbbbed1 100644 --- a/libgnucash/engine/gnc-option-date.hpp +++ b/libgnucash/engine/gnc-option-date.hpp @@ -32,7 +32,7 @@ #define GNC_OPTION_DATE_HPP_ #include "gnc-date.h" - +#include "gnc-datetime.hpp" #include #include /** @@ -167,9 +167,11 @@ RelativeDatePeriod gnc_relative_date_from_storage_string(const char*); * both in the current time zone. * * @param period The relative date period to use to calculate the concrete date. + * @param now_t Optional "now" date. Primarily for testing. * @return a time64. */ -time64 gnc_relative_date_to_time64(RelativeDatePeriod); +time64 gnc_relative_date_to_time64(RelativeDatePeriod, + time64 now_t = static_cast(GncDateTime())); /** * Add the display string to the provided std::ostream. diff --git a/libgnucash/engine/test/gtest-gnc-option.cpp b/libgnucash/engine/test/gtest-gnc-option.cpp index b1d1779c45..2a8dd380f4 100644 --- a/libgnucash/engine/test/gtest-gnc-option.cpp +++ b/libgnucash/engine/test/gtest-gnc-option.cpp @@ -950,6 +950,8 @@ class FakePrefsBackend int m_endabs = 0; int m_startperiod = GNC_ACCOUNTING_PERIOD_CYEAR; int m_endperiod = GNC_ACCOUNTING_PERIOD_CYEAR; + time64 m_startdate = 0; + time64 m_enddate = 0; public: int get_bool([[maybe_unused]] const char* group, const char* setting) { @@ -984,6 +986,23 @@ public: if (strcmp (setting, GNC_PREF_END_PERIOD) == 0) m_endperiod = value; } + + time64 get_time64([[maybe_unused]] const char* group, const char* setting) + { + if (strcmp (setting, GNC_PREF_START_DATE) == 0) + return m_startdate; + if (strcmp (setting, GNC_PREF_END_DATE) == 0) + return m_enddate; + return -1; + } + + void set_time64([[maybe_unused]] const char* group, const char* setting, time64 value) + { + if (strcmp (setting, GNC_PREF_START_DATE) == 0) + m_startdate = value; + if (strcmp (setting, GNC_PREF_END_DATE) == 0) + m_enddate = value; + } }; FakePrefsBackend fpb; @@ -1010,6 +1029,18 @@ static int set_int(const char* group, const char* setting, int value) return 1; } +static GVariant* get_value(const char* group, const char* setting) +{ + return g_variant_new("x", fpb.get_time64(group, setting)); +} + +static int set_value(const char* group, const char* setting, GVariant *value) +{ + fpb.set_int(group, setting, g_variant_get_int64(value)); + g_variant_unref(value); + return 1; +} + class GncOptionDateTest : public ::testing::Test { protected: @@ -1020,11 +1051,13 @@ protected: prefsbackend->set_bool = set_bool; prefsbackend->get_int = get_int; prefsbackend->set_int = set_int; + prefsbackend->get_value = get_value; + prefsbackend->set_value = set_value; } ~GncOptionDateTest() { g_free(prefsbackend); - gnc_clear_current_session(); + prefsbackend = nullptr; } }; @@ -1099,6 +1132,98 @@ TEST_F(GncOptionDateTest, test_gnc_relative_date_to_time64) gnc_relative_date_to_time64(RelativeDatePeriod::END_PREV_YEAR)); } +static void +set_fy(int year, int month, int day) +{ + auto start{static_cast(GncDateTime(GncDate(year, month, day), DayPart::start))}; + fpb.set_time64(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_DATE, start); +} + +static time64 +time64_from_ymd(int year, int month, int day) +{ + return static_cast(GncDateTime(GncDate(year, month, day))); +} + +static time64 +time64_from_ymd_start(int year, int month, int day) +{ + return static_cast(GncDateTime(GncDate(year, month, day), DayPart::start)); +} + +static time64 +time64_from_ymd_end(int year, int month, int day) +{ + return static_cast(GncDateTime(GncDate(year, month, day), DayPart::end)); +} + +TEST_F(GncOptionDateTest, test_fiscal_quarter_variation) +{ + fpb.set_bool(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_CHOICE_ABS, TRUE); + fpb.set_bool(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_CHOICE_ABS, TRUE); + + auto this_year{GncDate().year_month_day().year}; + auto last_year = this_year - 1; + set_fy(last_year, 7, 1); + auto at_date{time64_from_ymd(this_year, 1, 1)}; + EXPECT_EQ(time64_from_ymd_start(this_year, 1, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 3, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(last_year, 10, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(last_year, 12, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(this_year, 4, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_NEXT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 6, 30), + gnc_relative_date_to_time64(RelativeDatePeriod::END_NEXT_QUARTER, at_date)); + + at_date = time64_from_ymd(this_year, 2, 15); + EXPECT_EQ(time64_from_ymd_start(this_year, 1, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 3, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(last_year, 10, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(last_year, 12, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(this_year, 4, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_NEXT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 6, 30), + gnc_relative_date_to_time64(RelativeDatePeriod::END_NEXT_QUARTER, at_date)); + + at_date = time64_from_ymd(this_year, 3, 31); + EXPECT_EQ(time64_from_ymd_start(this_year, 1, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 3, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(last_year, 10, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(last_year, 12, 31), + gnc_relative_date_to_time64(RelativeDatePeriod::END_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(this_year, 4, 1), + gnc_relative_date_to_time64(RelativeDatePeriod::START_NEXT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 6, 30), + gnc_relative_date_to_time64(RelativeDatePeriod::END_NEXT_QUARTER, at_date)); + + set_fy(last_year, 4, 6); + + at_date = time64_from_ymd(this_year, 2, 15); + EXPECT_EQ(time64_from_ymd_start(this_year, 1, 6), + gnc_relative_date_to_time64(RelativeDatePeriod::START_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 4, 5), + gnc_relative_date_to_time64(RelativeDatePeriod::END_CURRENT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(last_year, 10, 6), + gnc_relative_date_to_time64(RelativeDatePeriod::START_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 1, 5), + gnc_relative_date_to_time64(RelativeDatePeriod::END_PREV_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_start(this_year, 4, 6), + gnc_relative_date_to_time64(RelativeDatePeriod::START_NEXT_QUARTER, at_date)); + EXPECT_EQ(time64_from_ymd_end(this_year, 7, 5), + gnc_relative_date_to_time64(RelativeDatePeriod::END_NEXT_QUARTER, at_date)); +} + class GncOptionDateOptionTest : public ::testing::Test { protected: @@ -1111,10 +1236,13 @@ protected: prefsbackend->set_bool = set_bool; prefsbackend->get_int = get_int; prefsbackend->set_int = set_int; + prefsbackend->get_value = get_value; + prefsbackend->set_value = set_value; } ~GncOptionDateOptionTest() { g_free(prefsbackend); + prefsbackend = nullptr; } GncOption m_option; @@ -1176,6 +1304,9 @@ TEST_F(GncDateOptionList, test_set_and_get_relative) TEST_F(GncDateOption, test_stream_out) { + fpb.set_bool(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_START_CHOICE_ABS, FALSE); + fpb.set_bool(GNC_PREFS_GROUP_ACCT_SUMMARY, GNC_PREF_END_CHOICE_ABS, FALSE); + time64 time1{static_cast(GncDateTime("2019-07-19 15:32:26 +05:00"))}; m_option.set_value(time1); std::ostringstream oss;