summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2018-08-28 13:46:37 +0200
committerEike Rathke <erack@redhat.com>2018-08-28 16:23:46 +0200
commit7f3c6efd859050c8f376b6820710e91fa9077ac4 (patch)
tree7b177de4a02917fcc4558794361fe076efdd5dad /tools
parentb57ed76361da672697eccd219b09bd358a967e0d (diff)
Move lcl_getHourMinuteSecond() to tools::Time::GetClock()
Also add fFractionOfSecond and nFractionDecimals to obtain the remaining fraction of second. In preparation to use this in the number formatter and other places that obtain the wall clock time particles, which likely so far use bad rounding as well. Change-Id: I4fbea4165c560646438b06c340756c97dafa7c78 Reviewed-on: https://gerrit.libreoffice.org/59700 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
Diffstat (limited to 'tools')
-rw-r--r--tools/source/datetime/ttime.cxx51
1 files changed, 51 insertions, 0 deletions
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index a8b3a5d52b58..d9bfc40dfc02 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -39,6 +39,7 @@
#endif
#include <sal/log.hxx>
+#include <rtl/math.hxx>
#include <tools/time.hxx>
#include <osl/diagnose.h>
@@ -269,6 +270,56 @@ double tools::Time::GetTimeInDays() const
return (nHour + (nMin / 60) + (nSec / (minInHour * secInMin)) + (nNanoSec / (minInHour * secInMin * nanoSecInSec))) / 24 * nSign;
}
+// static
+void tools::Time::GetClock( double fTimeInDays,
+ sal_uInt16& nHour, sal_uInt16& nMinute, sal_uInt16& nSecond,
+ double& fFractionOfSecond, int nFractionDecimals )
+{
+ const double fTime = fTimeInDays - rtl::math::approxFloor(fTimeInDays); // date part absent
+
+ // If 0 then full day (or no day), shortcut.
+ // If < 0 then approxFloor() effectively returned the ceiling (note this
+ // also holds for negative fTimeInDays values) because of a near identical
+ // value, shortcut this to a full day as well.
+ // If >= 1.0 (actually == 1.0) then fTimeInDays is a negative small value
+ // not significant for a representable time and approxFloor() returned -1,
+ // shortcut to 0:0:0, otherwise it would become 24:0:0.
+ if (fTime <= 0.0 || fTime >= 1.0)
+ {
+ nHour = nMinute = nSecond = 0;
+ return;
+ }
+
+ // In seconds, including milli and nano.
+ const double fRawSeconds = fTime * tools::Time::secondPerDay;
+
+ // Round to nanoseconds, which is the highest resolution this could be
+ // influenced by.
+ double fSeconds = rtl::math::round( fRawSeconds, 9);
+
+ // If this ended up as a full day the original value was very very close
+ // but not quite. Take that.
+ if (fSeconds >= tools::Time::secondPerDay)
+ fSeconds = fRawSeconds;
+
+ // Now do not round values (specifically not up), but truncate to the next
+ // magnitude, so 23:59:59.99 is still 23:59:59 and not 24:00:00 (or even
+ // 00:00:00 which Excel does).
+ nHour = fSeconds / tools::Time::secondPerHour;
+ fSeconds -= nHour * tools::Time::secondPerHour;
+ nMinute = fSeconds / tools::Time::secondPerMinute;
+ fSeconds -= nMinute * tools::Time::secondPerMinute;
+ nSecond = fSeconds;
+ fSeconds -= nSecond;
+
+ // Do not round the fraction, otherwise .999 would end up as .00 again.
+ if (nFractionDecimals > 0)
+ fFractionOfSecond = rtl::math::pow10Exp( std::trunc(
+ rtl::math::pow10Exp( fSeconds, nFractionDecimals)), -nFractionDecimals);
+ else
+ fFractionOfSecond = fSeconds;
+}
+
Time& tools::Time::operator =( const tools::Time& rTime )
{
nTime = rTime.nTime;