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/date-time.cpp') 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