mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Add GncDateTime constructor taking a GncDate as parameter
As a GncDate doesn't have any time information, this has to be made up. GnuCash uses 3 times-of-day quite a lot: - start-of-day (00:00 local time) - end-of-day (23:59 local time) - neutral time (10:59 utc, chosen to minimize day offsetting when converting to/from localtime) A second parameter to the new constructor will tell it to use one of these presets.
This commit is contained in:
parent
724f8aa784
commit
d1ff16138e
@ -100,6 +100,7 @@ public:
|
||||
GncDateTimeImpl() : m_time(boost::local_time::local_sec_clock::local_time(tzp.get(boost::gregorian::day_clock::local_day().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(const GncDateImpl& date, DayPart part = DayPart::neutral);
|
||||
GncDateTimeImpl(const std::string str);
|
||||
GncDateTimeImpl(PTime&& pt) : m_time(pt, tzp.get(pt.date().year())) {}
|
||||
GncDateTimeImpl(LDT&& ldt) : m_time(ldt) {}
|
||||
@ -132,10 +133,46 @@ public:
|
||||
std::string format_zulu(const char* format) const;
|
||||
private:
|
||||
Date m_greg;
|
||||
|
||||
friend GncDateTimeImpl::GncDateTimeImpl(const GncDateImpl&, DayPart);
|
||||
};
|
||||
|
||||
/* Member function definitions for GncDateTimeImpl.
|
||||
*/
|
||||
GncDateTimeImpl::GncDateTimeImpl(const GncDateImpl& date, DayPart part) :
|
||||
m_time(unix_epoch, utc_zone)
|
||||
{
|
||||
using TD = boost::posix_time::time_duration;
|
||||
static const TD start(0, 0, 0);
|
||||
static const TD neutral(10, 59, 0);
|
||||
static const TD end(23,59, 0);
|
||||
TD time_of_day;
|
||||
switch (part)
|
||||
{
|
||||
case DayPart::start:
|
||||
time_of_day = start;
|
||||
break;
|
||||
case DayPart::neutral:
|
||||
time_of_day = neutral;
|
||||
break;
|
||||
case DayPart::end:
|
||||
time_of_day = end;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto tz = utc_zone;
|
||||
if (part != DayPart::neutral)
|
||||
tz = tzp.get(date.m_greg.year());
|
||||
m_time = LDT(date.m_greg, time_of_day, tz, LDT::EXCEPTION_ON_ERROR);
|
||||
}
|
||||
catch(boost::gregorian::bad_year)
|
||||
{
|
||||
throw(std::invalid_argument("Time value is outside the supported year range."));
|
||||
}
|
||||
}
|
||||
|
||||
GncDateTimeImpl::GncDateTimeImpl(const std::string str) :
|
||||
m_time(unix_epoch, utc_zone)
|
||||
{
|
||||
@ -286,6 +323,9 @@ GncDateTime::GncDateTime(const std::string str) :
|
||||
m_impl(new GncDateTimeImpl(str)) {}
|
||||
GncDateTime::~GncDateTime() = default;
|
||||
|
||||
GncDateTime::GncDateTime(const GncDate& date, DayPart part) :
|
||||
m_impl(new GncDateTimeImpl(*(date.m_impl), part)) {}
|
||||
|
||||
void
|
||||
GncDateTime::now()
|
||||
{
|
||||
|
@ -36,6 +36,12 @@ typedef struct
|
||||
int day; //1-31
|
||||
} ymd;
|
||||
|
||||
enum class DayPart {
|
||||
start, // 00:00
|
||||
neutral, // 10:59
|
||||
end, // 23:59
|
||||
};
|
||||
|
||||
class GncDateTimeImpl;
|
||||
class GncDateImpl;
|
||||
class GncDate;
|
||||
@ -77,6 +83,21 @@ public:
|
||||
* @exception std::invalid_argument if the year is outside the constraints.
|
||||
*/
|
||||
GncDateTime(const struct tm tm);
|
||||
/** Construct a GncDateTime from a GncDate. As a GncDate doesn't contain time
|
||||
* information, the time will be set depending on the second parameter
|
||||
* to start of day, neutral or end of day.
|
||||
* @param date: A GncDate representing a date.
|
||||
* @param part: An optinoal DayPart indicating which time to use in the conversion.
|
||||
* This can be "DayPart::start" for start of day (00:00 local time),
|
||||
* "DayPart::neutral" for a neutral time (10:59 UTC, chosen to have the
|
||||
* least chance of date changes when crossing timezone borders),
|
||||
* "DayPart::end" for end of day (23:59 local time).
|
||||
* If omitted part defaults to DayPart::neutral.
|
||||
* Note the different timezone used for DayPart::neutral compared to the other
|
||||
* two options!
|
||||
* @exception std::invalid_argument if the year is outside the constraints.
|
||||
*/
|
||||
GncDateTime(const GncDate& date, DayPart part = DayPart::neutral);
|
||||
/** Construct a GncDateTime
|
||||
* @param str: A string representing the date and time in some
|
||||
* recognizable format. Note that if a timezone is not specified the
|
||||
@ -174,6 +195,8 @@ class GncDate
|
||||
|
||||
private:
|
||||
std::unique_ptr<GncDateImpl> m_impl;
|
||||
|
||||
friend GncDateTime::GncDateTime(const GncDate&, DayPart);
|
||||
};
|
||||
|
||||
#endif // __GNC_DATETIME_HPP__
|
||||
|
@ -71,6 +71,35 @@ TEST(gnc_datetime_constructors, test_struct_tm_constructor)
|
||||
EXPECT_EQ(tm1.tm_min, tm.tm_min);
|
||||
}
|
||||
|
||||
/* Note: the following tests for the constructor taking a GncDate as input parameter
|
||||
* use GncDateTime's format() member function to simplify the result checking.
|
||||
* If there's a bug in this member function, these tests may fail in addition
|
||||
* to the format test later in the test suite. Be sure to check that later
|
||||
* test as well in case any of the below constructor tests fails. */
|
||||
|
||||
TEST(gnc_datetime_constructors, test_gncdate_start_constructor)
|
||||
{
|
||||
const ymd aymd = { 2017, 04, 20 };
|
||||
GncDateTime atime(GncDate(aymd.year, aymd.month, aymd.day), DayPart::start);
|
||||
//Skipping timezone information as this can't be controlled.
|
||||
EXPECT_EQ(atime.format("%d-%m-%Y %H:%M:%S"), "20-04-2017 00:00:00");
|
||||
}
|
||||
|
||||
TEST(gnc_datetime_constructors, test_gncdate_end_constructor)
|
||||
{
|
||||
const ymd aymd = { 2046, 11, 06 };
|
||||
GncDateTime atime(GncDate(aymd.year, aymd.month, aymd.day), DayPart::end);
|
||||
//Skipping timezone information as this can't be controlled.
|
||||
EXPECT_EQ(atime.format("%d-%m-%Y %H:%M:%S"), "06-11-2046 23:59:00");
|
||||
}
|
||||
|
||||
TEST(gnc_datetime_constructors, test_gncdate_neutral_constructor)
|
||||
{
|
||||
const ymd aymd = { 2017, 04, 20 };
|
||||
GncDateTime atime(GncDate(aymd.year, aymd.month, aymd.day), DayPart::neutral);
|
||||
EXPECT_EQ(atime.format("%d-%m-%Y %H:%M:%S %z"), "20-04-2017 10:59:00 UTC");
|
||||
}
|
||||
|
||||
TEST(gnc_datetime_functions, test_format)
|
||||
{
|
||||
GncDateTime atime(2394187200); //2045-11-13 12:00:00 Z
|
||||
|
Loading…
Reference in New Issue
Block a user