/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// 922337 * HOUR_MASK = 9223370000000000000 largest possible value, 922338 // would be -9223364073709551616.
assert(HOUR_MASK * nHour >= 0 && "use tools::Duration with days instead!"); if (HOUR_MASK * nHour < 0)
nHour = 922337;
// But as is, GetHour() retrieves only sal_uInt16. Though retrieving in // nanoseconds or milliseconds might be possible this is all crap.
assert(nHour <= SAL_MAX_UINT16 && "use tools::Duration with days instead!"); if (nHour > SAL_MAX_UINT16)
nHour = SAL_MAX_UINT16;
// static void tools::Time::GetClock( double fTimeInDays,
sal_uInt16& nHour, sal_uInt16& nMinute, sal_uInt16& nSecond, double& fFractionOfSecond, int nFractionDecimals )
{ constdouble 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;
fFractionOfSecond = 0.0; return;
}
// In seconds, including milli and nano. constdouble fRawSeconds = fTime * tools::Time::secondPerDay;
// Round to nanoseconds most, which is the highest resolution this could be // influenced by, but if the original value included a date round to at // most 14 significant digits (including adding 4 for *86400), otherwise we // might end up with a fake precision of h:m:s.999999986 which in fact // should had been h:m:s+1 // BUT, leave at least 2 decimals to round. Which shouldn't be a problem in // practice because class Date can calculate only 8-digit days for it's // sal_Int16 year range, which exactly leaves us with 14-4-8=2. int nDec = 9; constdouble fAbsTimeInDays = fabs( fTimeInDays); if (fAbsTimeInDays >= 1.0)
{ constint nDig = static_cast<int>(ceil( log10( fAbsTimeInDays)));
nDec = std::clamp( 10 - nDig, 2, 9 );
} double fSeconds = rtl::math::round( fRawSeconds, nDec);
// 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;
assert(fSeconds < 1.0); // or back to the drawing board...
if (nFractionDecimals > 0)
{ // Do not simply round the fraction, otherwise .999 would end up as .00 // again. Truncate instead if rounding would round up into an integer // value.
fFractionOfSecond = rtl::math::round( fSeconds, nFractionDecimals); if (fFractionOfSecond >= 1.0)
fFractionOfSecond = rtl::math::pow10Exp( std::trunc(
rtl::math::pow10Exp( fSeconds, nFractionDecimals)), -nFractionDecimals);
} else
fFractionOfSecond = fSeconds;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.