Skip to content

Commit

Permalink
[gnc-datetime] add boost UK/US/ISO date parsers
Browse files Browse the repository at this point in the history
Thus "30 Sep 2024" and "30 September 2024" are accepted.
But ICU's "30 Sept 2024" is rightfully rejected.
  • Loading branch information
christopherlam committed Sep 8, 2024
1 parent d935ede commit 69bf156
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
13 changes: 11 additions & 2 deletions libgnucash/engine/gnc-datetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,16 @@ static constexpr auto ticks_per_second = INT64_C(1000000);
static constexpr auto ticks_per_second = INT64_C(1000000000);
#endif

/* Vector of date formats understood by gnucash and corresponding regex
* to parse each from an external source
/* Vector of date formats understood by gnucash and corresponding
* boost string->date or regex to parse each from an external source
* Note: while the format names are using a "-" as separator, the
* regexes will accept any of "-/.' " and will also work for dates
* without separators.
*/
const std::vector<GncDateFormat> GncDate::c_formats ({
GncDateFormat { N_("UK date"), boost::gregorian::from_uk_string },
GncDateFormat { N_("US date"), boost::gregorian::from_us_string },
GncDateFormat { N_("ISO date"), boost::gregorian::from_string },
GncDateFormat {
N_("y-m-d"),
"(?:" // either y-m-d
Expand Down Expand Up @@ -617,6 +620,12 @@ GncDateImpl::GncDateImpl(const std::string str, const std::string fmt) :
if (iter == GncDate::c_formats.cend())
throw std::invalid_argument(N_("Unknown date format specifier passed as argument."));

if (iter->m_str_to_date)
{
m_greg = (*iter->m_str_to_date)(str);
return;
}

boost::regex r(iter->m_re);
boost::smatch what;
if(!boost::regex_search(str, what, r)) // regex didn't find a match
Expand Down
9 changes: 9 additions & 0 deletions libgnucash/engine/gnc-datetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#include <memory>
#include <string>
#include <vector>
#include <functional>
#include <optional>

#include <boost/date_time/gregorian/gregorian.hpp>

typedef struct
{
Expand Down Expand Up @@ -172,6 +176,8 @@ class GncDateTime
* GncDate::c_formats class variable and work with those.
*/

using StringToDate = std::function<boost::gregorian::date(const std::string&)>;

class GncDateFormat
{
public:
Expand All @@ -182,13 +188,16 @@ class GncDateFormat
*/
GncDateFormat (const char* fmt, const char* re) :
m_fmt(fmt), m_re(re) {}
GncDateFormat (const char* fmt, StringToDate str_to_date) :
m_fmt(fmt), m_str_to_date(str_to_date) {}
/** A string representing the format. */
const std::string m_fmt;
private:
/** Regular expression associated with the format string. This is to and
* only be used internally by the gnc-datetime code.
*/
const std::string m_re;
std::optional<StringToDate> m_str_to_date;

friend class GncDateImpl;
};
Expand Down

0 comments on commit 69bf156

Please sign in to comment.