Resolves: tdf#127334 Increase tools::Duration accuracy epsilon unsharpness
... when converting from double, i.e. to 300 nanoseconds. Empirically determined.. Change-Id: I92c43b5f244923363af5d44bece9c155126ca343 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155324 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
This commit is contained in:
parent
0b5e88bc88
commit
46e672db80
2 changed files with 25 additions and 13 deletions
|
@ -31,8 +31,17 @@ public:
|
|||
minutes and seconds values here though. */
|
||||
Duration(const Time& rStart, const Time& rEnd);
|
||||
|
||||
/** Difference in days, like DateTime()-DateTime(). */
|
||||
explicit Duration(double fTimeInDays);
|
||||
/** Difference in days, like DateTime()-DateTime().
|
||||
|
||||
@param nAccuracyEpsilonNanoseconds
|
||||
Round for example by 1 nanosecond if it's just 1 off to a
|
||||
second, i.e. 0999999999 or 0000000001. This can be loosened if
|
||||
necessary. For example, if fTimeInDays is a date+time in
|
||||
"today's" range with a significant seconds resolution, an
|
||||
accuracy epsilon (=unsharpness) of ~300 is required. Hence default.
|
||||
Must be 0 <= nAccuracyEpsilonNanoseconds <= Time::nanoSecPerSec - 1.
|
||||
*/
|
||||
explicit Duration(double fTimeInDays, sal_uInt64 nAccuracyEpsilonNanoseconds = 300);
|
||||
|
||||
/** Time can be a limited duration as well and can have out-of-range
|
||||
values, it will be normalized. Sign of both days and Time must be equal
|
||||
|
|
|
@ -47,8 +47,9 @@ Duration::Duration(const Time& rStart, const Time& rEnd)
|
|||
}
|
||||
}
|
||||
|
||||
Duration::Duration(double fTimeInDays)
|
||||
Duration::Duration(double fTimeInDays, sal_uInt64 nAccuracyEpsilonNanoseconds)
|
||||
{
|
||||
assert(nAccuracyEpsilonNanoseconds <= Time::nanoSecPerSec - 1);
|
||||
double fInt, fFrac;
|
||||
if (fTimeInDays < 0.0)
|
||||
{
|
||||
|
@ -66,19 +67,21 @@ Duration::Duration(double fTimeInDays)
|
|||
fFrac *= Time::nanoSecPerDay;
|
||||
fFrac = ::rtl::math::approxFloor(fFrac);
|
||||
sal_Int64 nNS = static_cast<sal_Int64>(fFrac);
|
||||
// Round by 1 nanosecond if it's just 1 off to a second, i.e.
|
||||
// 0999999999 or 0000000001. This could be loosened to rounding by 2 or
|
||||
// such if necessary.
|
||||
const sal_Int64 nN = nNS % Time::nanoSecPerSec;
|
||||
if (std::abs(nN) == 1)
|
||||
nNS -= (nNS < 0) ? -1 : 1;
|
||||
else if (std::abs(nN) == Time::nanoSecPerSec - 1)
|
||||
if (nN)
|
||||
{
|
||||
nNS += (nNS < 0) ? -1 : 1;
|
||||
if (std::abs(nNS) >= Time::nanoSecPerDay)
|
||||
const sal_uInt64 nA = std::abs(nN);
|
||||
if (nA <= nAccuracyEpsilonNanoseconds)
|
||||
nNS -= (nNS < 0) ? -nN : nN;
|
||||
else if (nA >= Time::nanoSecPerSec - nAccuracyEpsilonNanoseconds)
|
||||
{
|
||||
mnDays += nNS / Time::nanoSecPerDay;
|
||||
nNS %= Time::nanoSecPerDay;
|
||||
const sal_Int64 nD = Time::nanoSecPerSec - nA;
|
||||
nNS += (nNS < 0) ? -nD : nD;
|
||||
if (std::abs(nNS) >= Time::nanoSecPerDay)
|
||||
{
|
||||
mnDays += nNS / Time::nanoSecPerDay;
|
||||
nNS %= Time::nanoSecPerDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
maTime.MakeTimeFromNS(nNS);
|
||||
|
|
Loading…
Reference in a new issue