Skip to content

Commit

Permalink
Add dateformat "Locale" to pick current locale
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherlam committed Sep 11, 2024
1 parent f2aff99 commit 9afa05d
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions libgnucash/engine/gnc-datetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/locale.hpp>
#include <boost/regex.hpp>
#include <unicode/smpdtfmt.h>
#include <unicode/locid.h>
#include <unicode/udat.h>
#include <unicode/parsepos.h>
#include <unicode/calendar.h>
#include <libintl.h>
#include <locale.h>
#include <map>
Expand Down Expand Up @@ -84,6 +89,10 @@ static constexpr auto ticks_per_second = INT64_C(1000000000);
* without separators.
*/
const std::vector<GncDateFormat> GncDate::c_formats ({
GncDateFormat {
N_("Locale"),
""
},
GncDateFormat {
N_("y-m-d"),
"(?:" // either y-m-d
Expand Down Expand Up @@ -607,6 +616,53 @@ GncDateTimeImpl::timestamp()
return str.substr(0, 8) + str.substr(9, 15);
}

static icu::Locale
get_LCTIME_locale()
{
const char* lc_time_locale = setlocale(LC_TIME, nullptr);

if (lc_time_locale == nullptr)
return icu::Locale::getDefault();

std::string localeStr(lc_time_locale);
size_t dotPos = localeStr.find('.');
if (dotPos != std::string::npos)
localeStr = localeStr.substr(0, dotPos);

return icu::Locale::createCanonical (localeStr.c_str());
}

static Date
use_icu_parser (const std::string str)
{
UErrorCode status = U_ZERO_ERROR;
icu::Locale locale = get_LCTIME_locale();

static std::unique_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateInstance(icu::DateFormat::kDefault, locale));
if (formatter == nullptr)
throw std::invalid_argument ("Cannot create date formatter.");

static std::unique_ptr<icu::Calendar> calendar(icu::Calendar::createInstance(locale, status));
if (U_FAILURE(status))
throw std::invalid_argument("Cannot create calendar instance.");
calendar->setLenient (false);

icu::UnicodeString input = icu::UnicodeString::fromUTF8(str);
icu::ParsePosition parsePos;

UDate date = formatter->parse(input, parsePos);
if (parsePos.getErrorIndex() != -1 || parsePos.getIndex() != input.length())
throw std::invalid_argument ("Cannot parse string");

calendar->setTime(date, status);
if (U_FAILURE(status))
throw std::invalid_argument ("Cannot set calendar time");

return Date (calendar->get(UCAL_YEAR, status),
calendar->get(UCAL_MONTH, status) + 1,
calendar->get(UCAL_DATE, status));
}

/* Member function definitions for GncDateImpl.
*/
GncDateImpl::GncDateImpl(const std::string str, const std::string fmt) :
Expand All @@ -617,6 +673,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_re == "")
{
m_greg = use_icu_parser (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

0 comments on commit 9afa05d

Please sign in to comment.