Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Flamefire committed Feb 21, 2024
2 parents 4fa93a9 + 0cb9683 commit b3ba758
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
3 changes: 3 additions & 0 deletions doc/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
- 1.85.0
- Breaking changes
- `collator` does no longer derive from `std::collator` avoiding possible type confusion
- `date_time` stores time in second resolution for the ICU backend, where sub-second resolution was added/fixed in Boost 1.81
- `comparator` in case of errors now throws on construction instead of on use as documented
- Character encoding conversion using IConv throws a `std::runtime_error` when the used IConv library is detected to be faulty (instead of running into an infinite loop)
- 1.84.0
- Breaking changes
- `to_title` for the WinAPI backend returns the string unchanged instead of an empty string
Expand Down
22 changes: 15 additions & 7 deletions src/boost/locale/icu/date_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ namespace boost { namespace locale { namespace impl_icu {
{
UErrorCode err = U_ZERO_ERROR;
calendar_.reset(icu::Calendar::createInstance(dat.locale(), err));
// Use accuracy of seconds, see #221
const double rounded_time = std::floor(calendar_->getTime(err) / U_MILLIS_PER_SECOND) * U_MILLIS_PER_SECOND;
calendar_->setTime(rounded_time, err);
check_and_throw_dt(err);
#if BOOST_LOCALE_ICU_VERSION < 402
// workaround old/invalid data, it should be 4 in general
Expand Down Expand Up @@ -110,13 +113,6 @@ namespace boost { namespace locale { namespace impl_icu {
return v;
}

void set_time(const posix_time& p) override
{
double utime = p.seconds * 1000.0 + p.nanoseconds / 1000000.0;
UErrorCode code = U_ZERO_ERROR;
calendar_->setTime(utime, code);
check_and_throw_dt(code);
}
void normalize() override
{
// Can't call complete() explicitly (protected)
Expand All @@ -125,6 +121,17 @@ namespace boost { namespace locale { namespace impl_icu {
calendar_->get(UCAL_YEAR, code);
check_and_throw_dt(code);
}

void set_time(const posix_time& p) override
{
// Ignore `p.nanoseconds / 1e6` for simplicity of users as there is no
// easy way to set the sub-seconds via `date_time`.
// Matches behavior of other backends that only have seconds resolution
const double utime = p.seconds * 1e3;
UErrorCode code = U_ZERO_ERROR;
calendar_->setTime(utime, code);
check_and_throw_dt(code);
}
posix_time get_time() const override
{
const double timeMs = get_time_ms();
Expand All @@ -146,6 +153,7 @@ namespace boost { namespace locale { namespace impl_icu {
check_and_throw_dt(code);
return result;
}

void set_option(calendar_option_type opt, int /*v*/) override
{
switch(opt) {
Expand Down
23 changes: 19 additions & 4 deletions test/test_date_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,13 @@ void test_main(int /*argc*/, char** /*argv*/)
// All at once
time_point = year(1989) + month(2) + day(5) + hour(7) + minute(9) + second(11);
TEST_EQ_FMT(time_point, "1989-03-05 07:09:11");
{
// Construction and setting of a timepoint to a fully specified value must be equal
// See issue #221
date_time explicit_time_point = year(1989) + month(2) + day(5) + hour(7) + minute(9) + second(11);
TEST(time_point == explicit_time_point);
TEST_EQ(time_point.time(), explicit_time_point.time());
}
// Partials:
time_point = year(1970) + february() + day(5);
TEST_EQ_FMT(time_point, "1970-02-05 07:09:11");
Expand Down Expand Up @@ -522,12 +529,20 @@ void test_main(int /*argc*/, char** /*argv*/)
// Difference in ns
{
const double sec = std::trunc(time_point.time()) + 0.5; // Stay inside current second
if(backend_name == "icu") { // Only ICU supports sub-second times
TEST(date_time(sec - 0.25) < date_time(sec));
TEST(date_time(sec + 0.25) > date_time(sec));
}
TEST(date_time(sec - 0.25) <= date_time(sec));
TEST(date_time(sec + 0.25) >= date_time(sec));
// See issue #221: Supporting subseconds is confusing,
// especially as it is/was only support by ICU
{
date_time var0, var1;
const auto floorTime = std::floor(sec);
var0.time(floorTime + 0.9);
var1.time(floorTime + 0.2);
TEST_EQ((var0 - var1) / second(), 0);
// Adding a seconds should lead to a second difference
var1 += second(1);
TEST_EQ((var1 - var0) / second(), 1);
}
}

TEST_EQ(time_point.get(day()), 5);
Expand Down

0 comments on commit b3ba758

Please sign in to comment.