Implement struct tm constructor and cast, offset accessor.

This commit is contained in:
John Ralls 2015-04-26 16:44:39 -07:00
parent e5861dc119
commit cbb01c94ae
3 changed files with 63 additions and 2 deletions

View File

@ -79,16 +79,29 @@ LDT_from_unix_local(const time64 time)
return LDT(temp, tz);
}
static LDT
LDT_from_struct_tm(const struct tm tm)
{
auto tdate = boost::gregorian::date_from_tm(tm);
auto tdur = boost::posix_time::time_duration(tm.tm_hour, tm.tm_min,
tm.tm_sec, 0);
auto tz = tzp.get(tdate.year());
return LDT(PTime(tdate, tdur), tz);
}
class GncDateTimeImpl
{
public:
GncDateTimeImpl() : m_time(unix_epoch, tzp.get(unix_epoch.date().year())) {}
GncDateTimeImpl(const time64 time) : m_time(LDT_from_unix_local(time)) {}
GncDateTimeImpl(const struct tm tm) : m_time(LDT_from_struct_tm(tm)) {}
GncDateTimeImpl(PTime&& pt) : m_time(pt, tzp.get(pt.date().year())) {}
GncDateTimeImpl(LDT&& ldt) : m_time(ldt) {}
operator time64() const;
operator struct tm() const;
void now() { m_time = boost::local_time::local_sec_clock::local_time(tzp.get(boost::gregorian::day_clock::local_day().year())); }
long offset() const;
private:
LDT m_time;
@ -102,6 +115,18 @@ GncDateTimeImpl::operator time64() const
return secs;
}
GncDateTimeImpl::operator struct tm() const
{
return to_tm(m_time);
}
long
GncDateTimeImpl::offset() const
{
auto offset = m_time.local_time() - m_time.utc_time();
return offset.total_seconds();
}
/* =================== Presentation-class Implementations ====================*/
GncDate::GncDate() : m_impl{new GncDateImpl} {}
GncDate::GncDate(int year, int month, int day) :
@ -115,7 +140,10 @@ GncDate::today()
}
GncDateTime::GncDateTime() : m_impl(new GncDateTimeImpl) {}
GncDateTime::GncDateTime(time64 time) : m_impl(new GncDateTimeImpl(time)) {}
GncDateTime::GncDateTime(const time64 time) :
m_impl(new GncDateTimeImpl(time)) {}
GncDateTime::GncDateTime(const struct tm tm) :
m_impl(new GncDateTimeImpl(tm)) {}
GncDateTime::~GncDateTime() = default;
void
@ -128,3 +156,14 @@ GncDateTime::operator time64() const
{
return m_impl->operator time64();
}
GncDateTime::operator struct tm() const
{
return m_impl->operator struct tm();
}
long
GncDateTime::offset() const
{
return m_impl->offset();
}

View File

@ -87,10 +87,13 @@ public:
* @param time: Seconds from the POSIX epoch.
* @exception std::invalid_argument if the year is outside the constraints.
*/
GncDateTime(time64 time);
GncDateTime(const time64 time);
GncDateTime(const struct tm tm);
~GncDateTime();
void now();
explicit operator time64() const;
explicit operator struct tm() const;
long offset() const;
bool isnull (void) { return m_impl == nullptr; }
private:

View File

@ -50,3 +50,22 @@ TEST(gnc_datetime_constructors, test_time64_constructor)
EXPECT_EQ(static_cast<time64>(atime), time);
}
TEST(gnc_datetime_constructors, test_struct_tm_constructor)
{
#ifdef HAVE_STRUCT_TM_GMTOFF
const struct tm tm {0, 0, 12, 13, 10, 145, 0, 0, 0, NULL, 0 };
#else
const struct tm tm {0, 0, 12, 13, 10, 145, 0, 0, 0 };
#endif
const time64 time = 2394187200; //2045-11-13 12:00:00 Z
GncDateTime atime(tm);
EXPECT_EQ(static_cast<time64>(atime), time);
const struct tm tm1 = static_cast<struct tm>(atime);
EXPECT_EQ(tm1.tm_year, tm.tm_year);
EXPECT_EQ(tm1.tm_mon, tm.tm_mon);
EXPECT_EQ(tm1.tm_mday, tm.tm_mday);
// We have to contort this a bit to handle offsets > 12, e.g. New Zealand during DST.
EXPECT_EQ((24 + tm1.tm_hour - atime.offset() / 3600) % 24, tm.tm_hour);
EXPECT_EQ(tm1.tm_min, tm.tm_min);
}