116 lines
3.5 KiB
ObjectPascal
116 lines
3.5 KiB
ObjectPascal
|
|
program convertSecondsToCompoundDuration(output);
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
suffixUnitWeek = 'wk';
|
|||
|
|
suffixUnitDay = 'd';
|
|||
|
|
suffixUnitHour = 'hr'; { Use `'h'` to be SI-compatible. }
|
|||
|
|
suffixUnitMinute = 'min';
|
|||
|
|
suffixUnitSecond = 'sec'; { NB: Only `'s'` is SI-approved. }
|
|||
|
|
|
|||
|
|
suffixSeparator = ' '; { A non-breaking space would be appropriate. }
|
|||
|
|
quantitySeparator = ', ';
|
|||
|
|
|
|||
|
|
{ Maximum expected length of `string` “12345 wk, 6 d, 7 hr, 8 min, 9 sec” }
|
|||
|
|
timeSpanPrintedMaximumLength = 4 * length(quantitySeparator) +
|
|||
|
|
20 + length(suffixUnitWeek) + 1 + length(suffixUnitDay) +
|
|||
|
|
2 + length(suffixUnitHour) + 2 + length(suffixUnitMinute) +
|
|||
|
|
2 + length(suffixUnitSecond) + 5 * length(suffixSeparator);
|
|||
|
|
|
|||
|
|
{ Units of time expressed in seconds. }
|
|||
|
|
minute = 60;
|
|||
|
|
hour = 60 * minute;
|
|||
|
|
day = 24 * hour;
|
|||
|
|
week = 7 * day;
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
wholeNumber = 0..maxInt;
|
|||
|
|
naturalNumber = 1..maxInt;
|
|||
|
|
|
|||
|
|
canonicalTimeSpan = record
|
|||
|
|
weeks: wholeNumber;
|
|||
|
|
days: 0..6;
|
|||
|
|
hours: 0..23;
|
|||
|
|
minutes: 0..59;
|
|||
|
|
seconds: 0..59;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
stringFitForTimeSpan = string(timeSpanPrintedMaximumLength);
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
\brief turns a time span expressed in seconds into a `canonicalTimeSpan`
|
|||
|
|
\param duration the non-negative duration expressed in seconds
|
|||
|
|
\return a `canonicalTimeSpan` representing \param duration seconds
|
|||
|
|
}
|
|||
|
|
function getCanonicalTimeSpan(duration: wholeNumber): canonicalTimeSpan;
|
|||
|
|
{ Perform `div`ision and update `duration`. }
|
|||
|
|
function split(protected unit: naturalNumber): wholeNumber;
|
|||
|
|
begin
|
|||
|
|
split := duration div unit;
|
|||
|
|
duration := duration mod unit
|
|||
|
|
end;
|
|||
|
|
var
|
|||
|
|
result: canonicalTimeSpan;
|
|||
|
|
begin
|
|||
|
|
with result do
|
|||
|
|
begin
|
|||
|
|
weeks := split(week);
|
|||
|
|
days := split(day);
|
|||
|
|
hours := split(hour);
|
|||
|
|
minutes := split(minute);
|
|||
|
|
seconds := duration
|
|||
|
|
end;
|
|||
|
|
{ In Pascal there needs to be _exactly_ one assignment to the }
|
|||
|
|
{ result variable bearing the same name as of the `function`. }
|
|||
|
|
getCanonicalTimeSpan := result
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
\brief turns a non-trivial duration into a string
|
|||
|
|
\param n a positive duration expressed in seconds
|
|||
|
|
\return \param n expressed in some human-readable form
|
|||
|
|
}
|
|||
|
|
function timeSpanString(protected n: naturalNumber): stringFitForTimeSpan;
|
|||
|
|
const
|
|||
|
|
qs = quantitySeparator;
|
|||
|
|
var
|
|||
|
|
result: stringFitForTimeSpan;
|
|||
|
|
begin
|
|||
|
|
with getCanonicalTimeSpan(n) do
|
|||
|
|
begin
|
|||
|
|
{ `:1` specifies the minimum-width. Omitting it would cause }
|
|||
|
|
{ the compiler to insert a vendor-defined default, e. g. 20. }
|
|||
|
|
writeStr(result, weeks:1, suffixSeparator, suffixUnitWeek);
|
|||
|
|
{ For strings, `:n` specifies the _exact_ width (padded with spaces). }
|
|||
|
|
writeStr(result, result:ord(weeks > 0) * length(result));
|
|||
|
|
|
|||
|
|
if days > 0 then
|
|||
|
|
begin
|
|||
|
|
writeStr(result, result, qs:ord(length(result) > 0) * length(qs),
|
|||
|
|
days:1, suffixSeparator, suffixUnitDay);
|
|||
|
|
end;
|
|||
|
|
if hours > 0 then
|
|||
|
|
begin
|
|||
|
|
writeStr(result, result, qs:ord(length(result) > 0) * length(qs),
|
|||
|
|
hours:1, suffixSeparator, suffixUnitHour);
|
|||
|
|
end;
|
|||
|
|
if minutes > 0 then
|
|||
|
|
begin
|
|||
|
|
writeStr(result, result, qs:ord(length(result) > 0) * length(qs),
|
|||
|
|
minutes:1, suffixSeparator, suffixUnitMinute);
|
|||
|
|
end;
|
|||
|
|
if seconds > 0 then
|
|||
|
|
begin
|
|||
|
|
writeStr(result, result, qs:ord(length(result) > 0) * length(qs),
|
|||
|
|
seconds:1, suffixSeparator, suffixUnitSecond);
|
|||
|
|
end
|
|||
|
|
end;
|
|||
|
|
timeSpanString := result
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{ === MAIN ============================================================= }
|
|||
|
|
begin
|
|||
|
|
writeLn( 7259, ' seconds are “', timeSpanString(7259), '”');
|
|||
|
|
writeLn( 86400, ' seconds are “', timeSpanString(86400), '”');
|
|||
|
|
writeLn(6000000, ' seconds are “', timeSpanString(6000000), '”')
|
|||
|
|
end.
|