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. --- src/date-time.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/date-time.cpp b/src/date-time.cpp index a139ea9..33b1590 100644 --- a/src/date-time.cpp +++ b/src/date-time.cpp @@ -27,42 +27,49 @@ namespace datetime { **** ***/ -DateTime::DateTime(GDateTime* gdt) +DateTime::DateTime() { - reset(gdt); } -DateTime& DateTime::operator=(GDateTime* gdt) +DateTime::DateTime(GTimeZone* gtz, GDateTime* gdt) { - reset(gdt); - return *this; + g_return_if_fail((gtz==nullptr) == (gdt==nullptr)); + + reset(gtz, gdt); } DateTime& DateTime::operator=(const DateTime& that) { + m_tz = that.m_tz; m_dt = that.m_dt; return *this; } DateTime::DateTime(time_t t) { + auto gtz = g_time_zone_new_local(); auto gdt = g_date_time_new_from_unix_local(t); - reset(gdt); + reset(gtz, gdt); + g_time_zone_unref(gtz); g_date_time_unref(gdt); } DateTime DateTime::NowLocal() { + auto gtz = g_time_zone_new_local(); auto gdt = g_date_time_new_now_local(); - DateTime dt(gdt); + DateTime dt(gtz, gdt); + g_time_zone_unref(gtz); g_date_time_unref(gdt); return dt; } DateTime DateTime::Local(int year, int month, int day, int hour, int minute, int seconds) { + auto gtz = g_time_zone_new_local(); auto gdt = g_date_time_new_local (year, month, day, hour, minute, seconds); - DateTime dt(gdt); + DateTime dt(gtz, gdt); + g_time_zone_unref(gtz); g_date_time_unref(gdt); return dt; } @@ -71,20 +78,51 @@ DateTime DateTime::to_timezone(const std::string& zone) const { auto gtz = g_time_zone_new(zone.c_str()); auto gdt = g_date_time_to_timezone(get(), gtz); - DateTime dt(gdt); + DateTime dt(gtz, gdt); g_time_zone_unref(gtz); g_date_time_unref(gdt); return dt; } +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); + 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; +} + +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); + 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; +} + DateTime DateTime::add_full(int years, int months, int days, int hours, int minutes, double seconds) const { auto gdt = g_date_time_add_full(get(), years, months, days, hours, minutes, seconds); - DateTime dt(gdt); + DateTime dt(m_tz.get(), gdt); g_date_time_unref(gdt); return dt; } +DateTime DateTime::add_days(int days) const +{ + return add_full(0, 0, days, 0, 0, 0); +} + GDateTime* DateTime::get() const { g_assert(m_dt); @@ -135,12 +173,25 @@ int64_t DateTime::to_unix() const return g_date_time_to_unix(get()); } -void DateTime::reset(GDateTime* in) +void DateTime::reset(GTimeZone* gtz, GDateTime* gdt) { - if (in) + g_return_if_fail ((gdt==nullptr) == (gtz==nullptr)); // all or nothin' + + if (gtz) + { + auto deleter = [](GTimeZone* tz){g_time_zone_unref(tz);}; + m_tz = std::shared_ptr(g_time_zone_ref(gtz), deleter); + g_assert(m_tz); + } + else + { + m_tz.reset(); + } + + if (gdt) { auto deleter = [](GDateTime* dt){g_date_time_unref(dt);}; - m_dt = std::shared_ptr(g_date_time_ref(in), deleter); + m_dt = std::shared_ptr(g_date_time_ref(gdt), deleter); g_assert(m_dt); } else -- cgit v1.2.3 From c940b70c65b1550fe65dbad5841adfe906cf0cdf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 14 Mar 2015 21:31:42 -0500 Subject: use the new DateTime::start_of_day() and DateTime::start_of_minute() functions. --- src/actions-live.cpp | 3 +-- src/actions.cpp | 4 +--- src/alarm-queue-simple.cpp | 2 +- src/menu.cpp | 4 ++-- src/planner-month.cpp | 7 +------ src/planner-upcoming.cpp | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/actions-live.cpp b/src/actions-live.cpp index 7efc2b2..121744a 100644 --- a/src/actions-live.cpp +++ b/src/actions-live.cpp @@ -119,8 +119,7 @@ void LiveActions::desktop_open_appointment(const Appointment& appt) void LiveActions::desktop_open_calendar_app(const DateTime& dt) { - const auto day_begins = dt.add_full(0, 0, 0, -dt.hour(), -dt.minute(), -dt.seconds()); - const auto gmt = day_begins.to_timezone("UTC"); + const auto gmt = dt.start_of_day().to_timezone("UTC"); auto cmd = gmt.format("evolution \"calendar:///?startdate=%Y%m%dT%H%M%SZ\""); execute_command(cmd.c_str()); } diff --git a/src/actions.cpp b/src/actions.cpp index 1b665cc..41c7f11 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -143,9 +143,7 @@ void on_calendar_activated(GSimpleAction * /*action*/, g_return_if_fail(t != 0); - // the client gave us a date; remove the HMS component from the resulting DateTime - auto dt = DateTime(t); - dt = dt.add_full (0, 0, 0, -dt.hour(), -dt.minute(), -dt.seconds()); + auto dt = DateTime(t).start_of_day(); static_cast(gself)->set_calendar_date(dt); } diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index fa6c0bc..f45e61a 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -102,7 +102,7 @@ bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const bool found = false; Appointment tmp; const auto now = m_clock->localtime(); - const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds()); + const auto beginning_of_minute = now.start_of_minute(); const auto appointments = m_planner->appointments().get(); g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); diff --git a/src/menu.cpp b/src/menu.cpp index f11de77..ff894bc 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -152,9 +152,9 @@ protected: const auto now = m_state->clock->localtime(); const auto calendar_day = m_state->calendar_month->month().get(); if ((profile() == Desktop) && !DateTime::is_same_day(now, calendar_day)) - begin = calendar_day.add_full (0, 0, 0, -calendar_day.hour(), -calendar_day.minute(), -calendar_day.seconds()); + begin = calendar_day.start_of_day(); else - begin = now.add_full (0, 0, 0, 0, 0, -now.seconds()); + begin = now.start_of_minute(); std::vector upcoming; for(const auto& a : m_state->calendar_upcoming->appointments().get()) diff --git a/src/planner-month.cpp b/src/planner-month.cpp index 5920daa..fd8a568 100644 --- a/src/planner-month.cpp +++ b/src/planner-month.cpp @@ -32,12 +32,7 @@ MonthPlanner::MonthPlanner(const std::shared_ptr& range_planner, m_range_planner(range_planner) { month().changed().connect([this](const DateTime& m){ - auto month_begin = m.add_full(0, // no years - 0, // no months - -(m.day_of_month()-1), - -m.hour(), - -m.minute(), - -m.seconds()); + 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); 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/src/planner-upcoming.cpp b/src/planner-upcoming.cpp index ed45955..338329c 100644 --- a/src/planner-upcoming.cpp +++ b/src/planner-upcoming.cpp @@ -33,7 +33,7 @@ UpcomingPlanner::UpcomingPlanner(const std::shared_ptr& range_plan { date().changed().connect([this](const DateTime& dt){ // set the range to the upcoming month - const auto b = dt.add_full(0, 0, -1, -dt.hour(), -dt.minute(), -dt.seconds()); + const auto b = dt.add_days(-1).start_of_day(); const auto e = b.add_full(0, 1, 0, 0, 0, 0); g_debug("%p setting date range to [%s..%s]", this, b.format("%F %T").c_str(), e.format("%F %T").c_str()); m_range_planner->range().set(std::pair(b,e)); -- cgit v1.2.3 From 6481c0ecf40df26eca71779a683aeeab9455f1f2 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 14 Mar 2015 21:33:51 -0500 Subject: sync the rest of the code with the changes to DateTime instantiation mentioned two commits ago --- src/clock-live.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/clock-live.cpp b/src/clock-live.cpp index 7f8bd1b..89541ae 100644 --- a/src/clock-live.cpp +++ b/src/clock-live.cpp @@ -68,7 +68,7 @@ public: g_assert(m_gtimezone != nullptr); auto gdt = g_date_time_new_now(m_gtimezone); - DateTime ret(gdt); + DateTime ret(m_gtimezone, gdt); g_date_time_unref(gdt); return ret; } -- cgit v1.2.3 From 61b00f51d58678c0a265c9e4a0fd35354fe5dc90 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 14 Mar 2015 22:33:26 -0500 Subject: in DateTime::Local() and DateTime::NowLocal(), avoid redundant construction of the local timezone. --- src/date-time.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/date-time.cpp b/src/date-time.cpp index 33b1590..46591e6 100644 --- a/src/date-time.cpp +++ b/src/date-time.cpp @@ -57,7 +57,7 @@ DateTime::DateTime(time_t t) DateTime DateTime::NowLocal() { auto gtz = g_time_zone_new_local(); - auto gdt = g_date_time_new_now_local(); + auto gdt = g_date_time_new_now(gtz); DateTime dt(gtz, gdt); g_time_zone_unref(gtz); g_date_time_unref(gdt); @@ -67,7 +67,7 @@ DateTime DateTime::NowLocal() DateTime DateTime::Local(int year, int month, int day, int hour, int minute, int seconds) { auto gtz = g_time_zone_new_local(); - auto gdt = g_date_time_new_local (year, month, day, hour, minute, seconds); + auto gdt = g_date_time_new(gtz, year, month, day, hour, minute, seconds); DateTime dt(gtz, gdt); g_time_zone_unref(gtz); g_date_time_unref(gdt); -- cgit v1.2.3 From fb36c642ce787c2ba2c9ec076250b12dac8c0546 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 14 Mar 2015 22:42:06 -0500 Subject: fix GAction leakage found while testing new unit tests with valgrind --- src/actions.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/actions.cpp b/src/actions.cpp index 41c7f11..839c9cd 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -223,18 +223,26 @@ Actions::Actions(const std::shared_ptr& state): auto v = create_default_header_state(); auto a = g_simple_action_new_stateful("desktop-header", nullptr, v); g_action_map_add_action(gam, G_ACTION(a)); + g_object_unref(a); + a = g_simple_action_new_stateful("desktop_greeter-header", nullptr, v); g_action_map_add_action(gam, G_ACTION(a)); + g_object_unref(a); + a = g_simple_action_new_stateful("phone-header", nullptr, v); g_action_map_add_action(gam, G_ACTION(a)); + g_object_unref(a); + a = g_simple_action_new_stateful("phone_greeter-header", nullptr, v); g_action_map_add_action(gam, G_ACTION(a)); + g_object_unref(a); // add the calendar action v = create_calendar_state(state); a = g_simple_action_new_stateful("calendar", G_VARIANT_TYPE_INT64, v); g_action_map_add_action(gam, G_ACTION(a)); g_signal_connect(a, "activate", G_CALLBACK(on_calendar_activated), this); + g_object_unref(a); /// /// Keep our GActionGroup's action's states in sync with m_state -- cgit v1.2.3 From 4dd066bb3534fe84ec4eed285422f043695febb7 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 Mar 2015 11:51:47 -0500 Subject: make utc variable name more sensible. --- src/actions-live.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/actions-live.cpp b/src/actions-live.cpp index 121744a..4d1f770 100644 --- a/src/actions-live.cpp +++ b/src/actions-live.cpp @@ -119,8 +119,8 @@ void LiveActions::desktop_open_appointment(const Appointment& appt) void LiveActions::desktop_open_calendar_app(const DateTime& dt) { - const auto gmt = dt.start_of_day().to_timezone("UTC"); - auto cmd = gmt.format("evolution \"calendar:///?startdate=%Y%m%dT%H%M%SZ\""); + const auto utc = dt.start_of_day().to_timezone("UTC"); + auto cmd = utc.format("evolution \"calendar:///?startdate=%Y%m%dT%H%M%SZ\""); execute_command(cmd.c_str()); } -- cgit v1.2.3 From 76c4567c8c674483e9e3b7286f78ab45115a8cf9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 Mar 2015 18:18:15 +0100 Subject: in DateTime::DateTime(GTimeZone*,GDateTime*), don't allow either argument to be nullptr --- src/date-time.cpp | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/date-time.cpp b/src/date-time.cpp index 46591e6..47ca047 100644 --- a/src/date-time.cpp +++ b/src/date-time.cpp @@ -33,7 +33,8 @@ DateTime::DateTime() DateTime::DateTime(GTimeZone* gtz, GDateTime* gdt) { - g_return_if_fail((gtz==nullptr) == (gdt==nullptr)); + g_return_if_fail(gtz!=nullptr); + g_return_if_fail(gdt!=nullptr); reset(gtz, gdt); } @@ -175,29 +176,14 @@ int64_t DateTime::to_unix() const void DateTime::reset(GTimeZone* gtz, GDateTime* gdt) { - g_return_if_fail ((gdt==nullptr) == (gtz==nullptr)); // all or nothin' + g_return_if_fail (gdt!=nullptr); + g_return_if_fail (gtz!=nullptr); - if (gtz) - { - auto deleter = [](GTimeZone* tz){g_time_zone_unref(tz);}; - m_tz = std::shared_ptr(g_time_zone_ref(gtz), deleter); - g_assert(m_tz); - } - else - { - m_tz.reset(); - } - - if (gdt) - { - auto deleter = [](GDateTime* dt){g_date_time_unref(dt);}; - m_dt = std::shared_ptr(g_date_time_ref(gdt), deleter); - g_assert(m_dt); - } - else - { - m_dt.reset(); - } + auto tz_deleter = [](GTimeZone* tz){g_time_zone_unref(tz);}; + m_tz = std::shared_ptr(g_time_zone_ref(gtz), tz_deleter); + + auto dt_deleter = [](GDateTime* dt){g_date_time_unref(dt);}; + m_dt = std::shared_ptr(g_date_time_ref(gdt), dt_deleter); } bool DateTime::operator<(const DateTime& that) const -- 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 --- src/date-time.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') 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. --- src/date-time.cpp | 60 +++++++++++++++++++++++++++++++++++---------------- src/planner-month.cpp | 4 ++-- 2 files changed, 44 insertions(+), 20 deletions(-) (limited to 'src') 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)); }); -- cgit v1.2.3