107 auto lingMgr = Linguistics::MessageUtilities::Manager::sThe.LookupHandler ();
108 static const String kCommaSpace_{
", "sv};
117 static const String kSpaceBeforeUnit_{
" "sv};
119 InternalNumericFormatType_ t = As<InternalNumericFormatType_> ();
120 bool isNeg = (t < 0);
121 InternalNumericFormatType_ timeLeft = t < 0 ? -t : t;
123 if (timeLeft >= kSecondsPerYear_) {
124 unsigned int nYears =
static_cast<unsigned int> (timeLeft / kSecondsPerYear_);
126 if (not result.
empty ()) {
127 result << kCommaSpace_;
129 result << nYears << kSpaceBeforeUnit_
130 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fYear, prettyPrintInfo.fLabels.fYears,
static_cast<int> (nYears));
131 timeLeft -= nYears * kSecondsPerYear_;
134 if (timeLeft >= kSecondsPerMonth_) {
135 unsigned int nMonths =
static_cast<unsigned int> (timeLeft / kSecondsPerMonth_);
137 if (not result.
empty ()) {
138 result << kCommaSpace_;
140 result <<
"{}"_f(nMonths) << kSpaceBeforeUnit_
141 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMonth, prettyPrintInfo.fLabels.fMonths,
static_cast<int> (nMonths));
142 timeLeft -= nMonths * kSecondsPerMonth_;
145 if (timeLeft >= kSecondsPerDay_) {
146 unsigned int nDays =
static_cast<unsigned int> (timeLeft / kSecondsPerDay_);
148 if (not result.
empty ()) {
149 result << kCommaSpace_;
151 result <<
"{}"_f(nDays) << kSpaceBeforeUnit_
152 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fDay, prettyPrintInfo.fLabels.fDays,
static_cast<int> (nDays));
153 timeLeft -= nDays * kSecondsPerDay_;
157 if (timeLeft >= kSecondsPerHour_) {
158 unsigned int nHours =
static_cast<unsigned int> (timeLeft / kSecondsPerHour_);
160 if (not result.
empty ()) {
161 result << kCommaSpace_;
163 result <<
"{}"_f(nHours) << kSpaceBeforeUnit_
164 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fHour, prettyPrintInfo.fLabels.fHours,
static_cast<int> (nHours));
165 timeLeft -= nHours * kSecondsPerHour_;
168 if (timeLeft >= kSecondsPerMinute_) {
169 unsigned int nMinutes =
static_cast<unsigned int> (timeLeft / kSecondsPerMinute_);
171 if (not result.
empty ()) {
172 result << kCommaSpace_;
174 result <<
"{}"_f(nMinutes) << kSpaceBeforeUnit_
175 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMinute, prettyPrintInfo.fLabels.fMinutes,
static_cast<int> (nMinutes));
176 timeLeft -= nMinutes * kSecondsPerMinute_;
180 int timeLeftAsInt =
static_cast<int> (timeLeft);
181 if (timeLeftAsInt != 0) {
182 Assert (timeLeftAsInt > 0);
183 if (not result.
empty ()) {
184 result += kCommaSpace_;
187 if (fabs (timeLeft - timeLeftAsInt) < 0.001) {
188 result <<
"{}"_f(
static_cast<int> (timeLeft)) << kSpaceBeforeUnit_
189 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fSecond, prettyPrintInfo.fLabels.fSeconds, timeLeftAsInt);
190 timeLeft -=
static_cast<int> (timeLeft);
193 result <<
"{:.3f}"_f(timeLeft) << kSpaceBeforeUnit_ << prettyPrintInfo.fLabels.fSeconds;
203 static constexpr bool kFirstSubSecondUnitDoDecimalPlaceImmediately_{
true};
205 uint16_t nMilliseconds =
static_cast<uint16_t
> (floor (timeLeft * 1.0e3));
206 Assert (0 <= nMilliseconds and nMilliseconds < 1000);
208 if (nMilliseconds > 2 or Math::NearlyEquals (timeLeft, .001) or Math::NearlyEquals (timeLeft, .002)) {
209 if (not result.
empty ()) {
210 result << kCommaSpace_;
212 if (kFirstSubSecondUnitDoDecimalPlaceImmediately_) {
214 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMilliSecond, prettyPrintInfo.fLabels.fMilliSeconds, nMilliseconds);
218 result << int (nMilliseconds) << kSpaceBeforeUnit_
219 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMilliSecond, prettyPrintInfo.fLabels.fMilliSeconds, nMilliseconds);
220 timeLeft -= 1.0e-3 * nMilliseconds;
223 uint16_t nMicroSeconds =
static_cast<uint16_t
> (floor (timeLeft * 1.0e6));
224 if (nMicroSeconds > 0) {
225 if (not result.
empty ()) {
226 result << kCommaSpace_;
228 if (kFirstSubSecondUnitDoDecimalPlaceImmediately_) {
230 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMicroSecond, prettyPrintInfo.fLabels.fMicroSeconds, nMicroSeconds);
234 result << int (nMicroSeconds) << kSpaceBeforeUnit_
235 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fMicroSecond, prettyPrintInfo.fLabels.fMicroSeconds, nMicroSeconds);
236 timeLeft -= 1.0e-6 * nMicroSeconds;
239 uint16_t nNanoSeconds =
static_cast<uint16_t
> (floor (timeLeft * 1.0e9));
240 if (nNanoSeconds > 0) {
241 if (not result.
empty ()) {
242 result << kCommaSpace_;
244 if (kFirstSubSecondUnitDoDecimalPlaceImmediately_) {
246 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fNanoSecond, prettyPrintInfo.fLabels.fNanoSeconds, nNanoSeconds);
250 result << int (nMicroSeconds) << kSpaceBeforeUnit_
251 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fNanoSecond, prettyPrintInfo.fLabels.fNanoSecond, nNanoSeconds);
252 timeLeft -= 1.0e-9 * nNanoSeconds;
255 Duration::InternalNumericFormatType_ nPicoSeconds = timeLeft * 1.0e12;
256 if (nPicoSeconds > 1.0e-5) {
257 if (not result.
empty ()) {
258 result << kCommaSpace_;
260 Duration::InternalNumericFormatType_ extraBits = nPicoSeconds - floor (nPicoSeconds);
261 if (extraBits > 1.0e-2) {
262 result << nPicoSeconds << kSpaceBeforeUnit_
263 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fPicoSecond, prettyPrintInfo.fLabels.fPicoSeconds, 2);
266 result << int (nPicoSeconds) << kSpaceBeforeUnit_
267 << lingMgr->PluralizeNoun (prettyPrintInfo.fLabels.fPicoSecond, prettyPrintInfo.fLabels.fPicoSeconds, int (nPicoSeconds));
272 if (result.
empty ()) {
273 result <<
"0"sv << kSpaceBeforeUnit_ << prettyPrintInfo.fLabels.fSeconds;
276 static const String kNeg_{
"-"sv};
277 result = kNeg_ + result;
284 InternalNumericFormatType_ t = As<InternalNumericFormatType_> ();
285 bool isNeg = (t < 0);
286 InternalNumericFormatType_ absT = isNeg ? -t : t;
287 if (absT < agePrettyPrintInfo.fNowThreshold) {
288 return agePrettyPrintInfo.fLabels.fNow;
291 String suffix = isNeg ? agePrettyPrintInfo.fLabels.fAgo : agePrettyPrintInfo.fLabels.fFromNow;
293 auto fmtDate = [suffix] (
int timeInSelectedUnit,
const String& singularUnit,
const String& pluralUnit) ->
String {
294 String label = Linguistics::MessageUtilities::Manager::sThe.PluralizeNoun (singularUnit, pluralUnit, timeInSelectedUnit);
295 return "{} {} {}"_f(timeInSelectedUnit, label, suffix);
298 constexpr InternalNumericFormatType_ kShowAsMinutesIfLess_ = 55 * kSecondsPerMinute_;
299 constexpr InternalNumericFormatType_ kShowHoursIfLess_ = 23 * kSecondsPerHour_;
300 constexpr InternalNumericFormatType_ kShowDaysIfLess_ = 14 * kSecondsPerDay_;
301 constexpr InternalNumericFormatType_ kShowWeeksIfLess_ = 59 * kSecondsPerDay_;
302 constexpr InternalNumericFormatType_ kShowMonthsIfLess_ = 11 * kSecondsPerMonth_;
304 if (absT < kShowAsMinutesIfLess_) {
305 return fmtDate (Math::Round<int> (absT / kSecondsPerMinute_), prettyPrintInfo.fLabels.fMinute, prettyPrintInfo.fLabels.fMinutes);
307 if (absT < kShowHoursIfLess_) {
308 return fmtDate (Math::Round<int> (absT / kSecondsPerHour_), prettyPrintInfo.fLabels.fHour, prettyPrintInfo.fLabels.fHours);
310 if (absT < kShowDaysIfLess_ and not Math::NearlyEquals (absT,
static_cast<InternalNumericFormatType_
> (kSecondsPerWeek_), 1.0)) {
311 return fmtDate (Math::Round<int> (absT / kSecondsPerDay_), prettyPrintInfo.fLabels.fDay, prettyPrintInfo.fLabels.fDays);
313 if (absT < kShowWeeksIfLess_ and not Math::NearlyEquals (absT,
static_cast<InternalNumericFormatType_
> (kSecondsPerMonth_), 1.0)) {
314 return fmtDate (Math::Round<int> (absT / kSecondsPerWeek_), prettyPrintInfo.fLabels.fWeek, prettyPrintInfo.fLabels.fWeeks);
316 if (absT < kShowMonthsIfLess_) {
317 return fmtDate (Math::Round<int> (absT / kSecondsPerMonth_), prettyPrintInfo.fLabels.fMonth, prettyPrintInfo.fLabels.fMonths);
319 return fmtDate (Math::Round<int> (absT / kSecondsPerYear_), prettyPrintInfo.fLabels.fYear, prettyPrintInfo.fLabels.fYears);