From db5b700c7c116c73283019b3fbf823a23639a405 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 14 Mar 2015 21:20:30 -0500 Subject: Add DateTime::start_of_day() to use instead of the add_hours(-hours()) trick, which doesn't work on days when DST changes. Implementing this requires DateTime objects to keep their own GTimeZone pointer, since the one inside GDateTime is private and can't be used for DateTime::start_of_day()'s call to g_date_time_new(). As a result the public API of DateTime changes, since we'll need a GTimeZone when constructing or assigning from a GDateTime pointer. --- include/datetime/date-time.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'include/datetime') diff --git a/include/datetime/date-time.h b/include/datetime/date-time.h index 4be35f7..6e73ff3 100644 --- a/include/datetime/date-time.h +++ b/include/datetime/date-time.h @@ -38,13 +38,15 @@ public: static DateTime NowLocal(); static DateTime Local(int years, int months, int days, int hours, int minutes, int seconds); + DateTime(); explicit DateTime(time_t t); - explicit DateTime(GDateTime* in=nullptr); - DateTime& operator=(GDateTime* in); + DateTime(GTimeZone* tz, GDateTime* dt); DateTime& operator=(const DateTime& in); DateTime to_timezone(const std::string& zone) const; + DateTime start_of_day() const; + DateTime start_of_minute() const; + DateTime add_days(int days) const; DateTime add_full(int years, int months, int days, int hours, int minutes, double seconds) const; - void reset(GDateTime* in=nullptr); GDateTime* get() const; GDateTime* operator()() const {return get();} @@ -69,6 +71,8 @@ public: bool is_set() const { return m_dt != nullptr; } private: + void reset(GTimeZone*, GDateTime*); + std::shared_ptr m_tz; std::shared_ptr m_dt; }; -- cgit v1.2.3 From 67510bd5a582762648a96d7b42024c4f181ece8e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 Mar 2015 18:22:33 +0100 Subject: in DateTime::is_set(), include timezone test --- include/datetime/date-time.h | 2 +- src/date-time.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include/datetime') diff --git a/include/datetime/date-time.h b/include/datetime/date-time.h index 6e73ff3..8fa1569 100644 --- a/include/datetime/date-time.h +++ b/include/datetime/date-time.h @@ -68,7 +68,7 @@ public: static bool is_same_day(const DateTime& a, const DateTime& b); static bool is_same_minute(const DateTime& a, const DateTime& b); - bool is_set() const { return m_dt != nullptr; } + bool is_set() const { return m_tz && m_dt; } private: void reset(GTimeZone*, GDateTime*); diff --git a/src/date-time.cpp b/src/date-time.cpp index 47ca047..4176d06 100644 --- a/src/date-time.cpp +++ b/src/date-time.cpp @@ -88,7 +88,6 @@ DateTime DateTime::to_timezone(const std::string& zone) const DateTime DateTime::start_of_day() const { g_assert(is_set()); - g_assert(m_tz.get() != nullptr); int y=0, m=0, d=0; ymd(y, m, d); @@ -101,7 +100,6 @@ DateTime DateTime::start_of_day() const DateTime DateTime::start_of_minute() const { g_assert(is_set()); - g_assert(m_tz.get() != nullptr); int y=0, m=0, d=0; ymd(y, m, d); -- cgit v1.2.3 From 273c3b3829c9a3e853d0b6b0a32ae87cc3c6852b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 Mar 2015 21:07:54 +0100 Subject: add DateTime::end_of_month(), DateTime::end_of_day(). Add unit tests for them. --- include/datetime/date-time.h | 8 ++- src/date-time.cpp | 60 ++++++++++++------ src/planner-month.cpp | 4 +- tests/CMakeLists.txt | 1 + tests/manual-test-snap.cpp | 2 +- tests/test-alarm-queue.cpp | 4 +- tests/test-datetime.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++ tests/test-live-actions.cpp | 14 +++-- tests/test-snap.cpp | 7 +-- 9 files changed, 208 insertions(+), 35 deletions(-) create mode 100644 tests/test-datetime.cpp (limited to 'include/datetime') diff --git a/include/datetime/date-time.h b/include/datetime/date-time.h index 8fa1569..7dfc207 100644 --- a/include/datetime/date-time.h +++ b/include/datetime/date-time.h @@ -36,17 +36,21 @@ class DateTime { public: static DateTime NowLocal(); - static DateTime Local(int years, int months, int days, int hours, int minutes, int seconds); + static DateTime Local(int year, int month, int day, int hour, int minute, double seconds); DateTime(); explicit DateTime(time_t t); DateTime(GTimeZone* tz, GDateTime* dt); + DateTime(GTimeZone* tz, int year, int month, int day, int hour, int minute, double seconds); DateTime& operator=(const DateTime& in); DateTime to_timezone(const std::string& zone) const; + DateTime start_of_month() const; DateTime start_of_day() const; DateTime start_of_minute() const; + DateTime end_of_day() const; + DateTime end_of_month() const; DateTime add_days(int days) const; - DateTime add_full(int years, int months, int days, int hours, int minutes, double seconds) const; + DateTime add_full(int year, int month, int day, int hour, int minute, double seconds) const; GDateTime* get() const; GDateTime* operator()() const {return get();} diff --git a/src/date-time.cpp b/src/date-time.cpp index 4176d06..689688c 100644 --- a/src/date-time.cpp +++ b/src/date-time.cpp @@ -39,6 +39,15 @@ DateTime::DateTime(GTimeZone* gtz, GDateTime* gdt) reset(gtz, gdt); } +DateTime::DateTime(GTimeZone* gtz, int year, int month, int day, int hour, int minute, double seconds) +{ + g_return_if_fail(gtz!=nullptr); + + auto gdt = g_date_time_new(gtz, year, month, day, hour, minute, seconds); + reset(gtz, gdt); + g_date_time_unref(gdt); +} + DateTime& DateTime::operator=(const DateTime& that) { m_tz = that.m_tz; @@ -65,13 +74,11 @@ DateTime DateTime::NowLocal() return dt; } -DateTime DateTime::Local(int year, int month, int day, int hour, int minute, int seconds) +DateTime DateTime::Local(int year, int month, int day, int hour, int minute, double seconds) { auto gtz = g_time_zone_new_local(); - auto gdt = g_date_time_new(gtz, year, month, day, hour, minute, seconds); - DateTime dt(gtz, gdt); + DateTime dt(gtz, year, month, day, hour, minute, seconds); g_time_zone_unref(gtz); - g_date_time_unref(gdt); return dt; } @@ -85,33 +92,50 @@ DateTime DateTime::to_timezone(const std::string& zone) const return dt; } +DateTime DateTime::end_of_day() const +{ + g_assert(is_set()); + + return add_days(1).start_of_day().add_full(0,0,0,0,0,-1); +} + +DateTime DateTime::end_of_month() const +{ + g_assert(is_set()); + + return add_full(0,1,0,0,0,0).start_of_month().add_full(0,0,0,0,0,-1); +} + +DateTime DateTime::start_of_month() const +{ + g_assert(is_set()); + + int year=0, month=0, day=0; + ymd(year, month, day); + return DateTime(m_tz.get(), year, month, 1, 0, 0, 0); +} + DateTime DateTime::start_of_day() const { g_assert(is_set()); - int y=0, m=0, d=0; - ymd(y, m, d); - auto gdt = g_date_time_new(m_tz.get(), y, m, d, 0, 0, 0); - DateTime dt(m_tz.get(), gdt); - g_date_time_unref(gdt); - return dt; + int year=0, month=0, day=0; + ymd(year, month, day); + return DateTime(m_tz.get(), year, month, day, 0, 0, 0); } DateTime DateTime::start_of_minute() const { g_assert(is_set()); - int y=0, m=0, d=0; - ymd(y, m, d); - auto gdt = g_date_time_new(m_tz.get(), y, m, d, hour(), minute(), 0); - DateTime dt(m_tz.get(), gdt); - g_date_time_unref(gdt); - return dt; + int year=0, month=0, day=0; + ymd(year, month, day); + return DateTime(m_tz.get(), year, month, day, hour(), minute(), 0); } -DateTime DateTime::add_full(int years, int months, int days, int hours, int minutes, double seconds) const +DateTime DateTime::add_full(int year, int month, int day, int hour, int minute, double seconds) const { - auto gdt = g_date_time_add_full(get(), years, months, days, hours, minutes, seconds); + auto gdt = g_date_time_add_full(get(), year, month, day, hour, minute, seconds); DateTime dt(m_tz.get(), gdt); g_date_time_unref(gdt); return dt; diff --git a/src/planner-month.cpp b/src/planner-month.cpp index fd8a568..cdae26f 100644 --- a/src/planner-month.cpp +++ b/src/planner-month.cpp @@ -32,8 +32,8 @@ MonthPlanner::MonthPlanner(const std::shared_ptr& range_planner, m_range_planner(range_planner) { month().changed().connect([this](const DateTime& m){ - auto month_begin = m.start_of_day().add_full(0, 0, -(m.day_of_month()-1), 0, 0, 0); - auto month_end = month_begin.add_full(0, 1, 0, 0, 0, -0.1); + auto month_begin = m.start_of_month(); + auto month_end = m.end_of_month(); g_debug("PlannerMonth %p setting calendar month range: [%s..%s]", this, month_begin.format("%F %T").c_str(), month_end.format("%F %T").c_str()); m_range_planner->range().set(std::pair(month_begin,month_end)); }); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 20e744a..25fe5dc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,6 +47,7 @@ function(add_test_by_name name) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) endfunction() +add_test_by_name(test-datetime) add_test_by_name(test-snap) add_test_by_name(test-actions) add_test_by_name(test-alarm-queue) diff --git a/tests/manual-test-snap.cpp b/tests/manual-test-snap.cpp index 94c1ded..22ef137 100644 --- a/tests/manual-test-snap.cpp +++ b/tests/manual-test-snap.cpp @@ -71,7 +71,7 @@ int main(int argc, const char* argv[]) a.uid = "D4B57D50247291478ED31DED17FF0A9838DED402"; a.type = Appointment::UBUNTU_ALARM; a.begin = DateTime::Local(2014, 12, 25, 0, 0, 0); - a.end = a.begin.add_full(0,0,1,0,0,-1); + a.end = a.begin.end_of_day(); auto loop = g_main_loop_new(nullptr, false); auto on_snooze = [loop](const Appointment& appt){ diff --git a/tests/test-alarm-queue.cpp b/tests/test-alarm-queue.cpp index 0492539..3fdf787 100644 --- a/tests/test-alarm-queue.cpp +++ b/tests/test-alarm-queue.cpp @@ -69,7 +69,7 @@ protected: { const auto now = m_state->clock->localtime(); const auto tomorrow_begin = now.add_days(1).start_of_day(); - const auto tomorrow_end = tomorrow_begin.add_full(0, 0, 1, 0, 0, -1); + const auto tomorrow_end = tomorrow_begin.end_of_day(); Appointment a1; // an alarm clock appointment a1.color = "red"; @@ -81,7 +81,7 @@ protected: a1.end = tomorrow_end; const auto ubermorgen_begin = now.add_days(2).start_of_day(); - const auto ubermorgen_end = ubermorgen_begin.add_full(0, 0, 1, 0, 0, -1); + const auto ubermorgen_end = ubermorgen_begin.end_of_day(); Appointment a2; // a non-alarm appointment a2.color = "green"; diff --git a/tests/test-datetime.cpp b/tests/test-datetime.cpp new file mode 100644 index 0000000..41f78fb --- /dev/null +++ b/tests/test-datetime.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include "glib-fixture.h" + +using namespace unity::indicator::datetime; + +/*** +**** +***/ + +class DateTimeFixture: public GlibFixture +{ + public: + + DateTimeFixture() =default; + virtual ~DateTimeFixture() =default; + + private: + + typedef GlibFixture super; + + protected: + + GRand * m_rand = nullptr; + + virtual void SetUp() override + { + super::SetUp(); + + m_rand = g_rand_new(); + } + + virtual void TearDown() override + { + g_clear_pointer(&m_rand, g_rand_free); + + super::TearDown(); + } + + DateTime random_day() + { + return DateTime::Local(g_rand_int_range(m_rand, 1970, 3000), + g_rand_int_range(m_rand, 1, 13), + g_rand_int_range(m_rand, 1, 29), + g_rand_int_range(m_rand, 0, 24), + g_rand_int_range(m_rand, 0, 60), + g_rand_double_range(m_rand, 0, 60.0)); + } +}; + +/*** +**** +***/ + +TEST_F(DateTimeFixture, StartAndEnd) +{ + const int n_iterations{10000}; + + for (int i{0}; icalendar_month->appointments().set(std::vector({a1, a2})); diff --git a/tests/test-snap.cpp b/tests/test-snap.cpp index e7161d3..3dd4501 100644 --- a/tests/test-snap.cpp +++ b/tests/test-snap.cpp @@ -109,10 +109,9 @@ protected: appt.url = "alarm:///hello-world"; appt.uid = "D4B57D50247291478ED31DED17FF0A9838DED402"; appt.type = Appointment::EVENT; - auto begin = DateTime::Local(2014,12,25,0,0,0); - auto end = begin.add_full(0,0,1,0,0,-1); - appt.begin = begin; - appt.end = end; + const auto christmas = DateTime::Local(2015,12,25,0,0,0); + appt.begin = christmas.start_of_day(); + appt.end = christmas.end_of_day(); service = dbus_test_service_new(nullptr); -- cgit v1.2.3