Task

Write a function or program which:

   takes a positive integer representing a duration in seconds as input (e.g., 100), and
   returns a string which shows the same duration decomposed into:
   weeks,
   days, 
   hours, 
   minutes,   and 
   seconds.
This is detailed below (e.g., "2 hr, 59 sec").



Demonstrate that it passes the following three test-cases:

Test Cases


 input number

 output string


 7259

 2 hr, 59 sec


 86400

 1 d


 6000000

 9 wk, 6 d, 10 hr, 40 min

Details
The following five units should be used:



 unit

 suffix used in output

 conversion


 week

 wk

 1 week = 7 days


 day

 d

 1 day = 24 hours


 hour

 hr

 1 hour = 60 minutes


 minute

 min

 1 minute = 60 seconds


 second

 sec



However, only include quantities with non-zero values in the output (e.g., return "1 d" and not "0 wk, 1 d, 0 hr, 0 min, 0 sec").

Give larger units precedence over smaller ones as much as possible (e.g., return 2 min, 10 sec and not 1 min, 70 sec or 130 sec)

Mimic the formatting shown in the test-cases (quantities sorted from largest unit to smallest and separated by comma+space; value and unit of each quantity separated by space).




# MODE to hold the compound duration #
MODE DURATION = STRUCT( INT weeks, days, hours, minutes, seconds );
 
# returns seconds converted to a DURATION #
OP TODURATION = ( LONG INT seconds )DURATION:
   BEGIN
       LONG INT time     := seconds;
       DURATION result   := DURATION( 0, 0, 0, 0, 0 );
       seconds OF result := SHORTEN ( time MOD  60 );
       time OVERAB 60;
       minutes OF result := SHORTEN ( time MOD  60 );
       time OVERAB 60;
       hours   OF result := SHORTEN ( time MOD  24 );
       time OVERAB 24;
       days    OF result := SHORTEN ( time MOD   7 );
       time OVERAB 7;
       weeks   OF result := SHORTEN   time;
       result
   END # DURATION # ;# returns seconds converted to a DURATION #
OP TODURATION = ( INT seconds )DURATION: TODURATION LENG seconds;
 
# returns a readable form of the DURATION #
OP TOSTRING = ( DURATION t )STRING:
   BEGIN
       STRING result    := "";
       STRING separator := "";
       IF weeks   OF t /= 0 THEN result +:= separator + whole( weeks   OF t, 0 ) + " wk";  separator := ", " FI;
       IF days    OF t /= 0 THEN result +:= separator + whole( days    OF t, 0 ) + " d";   separator := ", " FI;
       IF hours   OF t /= 0 THEN result +:= separator + whole( hours   OF t, 0 ) + " hr";  separator := ", " FI;
       IF minutes OF t /= 0 THEN result +:= separator + whole( minutes OF t, 0 ) + " min"; separator := ", " FI;
       IF seconds OF t /= 0 THEN result +:= separator + whole( seconds OF t, 0 ) + " sec"; separator := ", " FI;
       IF result = ""
       THEN
           # duration is 0 #
           result := "0 sec"
       FI;
       result
   END # TOSTRING # ;
 
# test cases #
print( ( TOSTRING TODURATION    7259, newline ) );
print( ( TOSTRING TODURATION   86400, newline ) );
print( ( TOSTRING TODURATION 6000000, newline ) )