Convert seconds to compound duration: Difference between revisions

(145 intermediate revisions by 55 users not shown)
Line 1:
{{task}}
[[Category:Date and time]]
 
;Task:
Write a function or program which:
* &nbsp; takes a positive integer representing a duration in seconds as input (e.g., <code>100</code>), and
* &nbsp; returns a string which shows the same duration decomposed into weeks, days, hours, minutes, and seconds as detailed below (e.g., "<code>1 min, 40 sec</code>").:
:::* &nbsp; weeks,
:::* &nbsp; days,
:::* &nbsp; hours,
:::* &nbsp; minutes, &nbsp; and
:::* &nbsp; seconds.
 
This is detailed below (e.g., "<code>2 hr, 59 sec</code>").
 
 
<br>
Demonstrate that it passes the following three test-cases:
 
<p style="font-size:115%; margin:1em 0 0.5em 0">'''''Test Cases'''''</p>
 
:::::{| class="wikitable"
|-
! input number
Line 28 ⟶ 36:
<p style="font-size:115%; margin:1em 0 0.5em 0">'''''Details'''''</p>
 
The following five units should be used:
<ul>
:::::{| class="wikitable"
<li>The following five units should be used:
{| class="wikitable"
|-
! unit
Line 50 ⟶ 57:
| minute
| <code style="background:#eee">min</code>
| 1 minutesminute = 60 seconds
|-
| second
Line 56 ⟶ 63:
|
|}
</li>
 
<li>However, '''only''' include quantities with non-zero values in the output (e.g., return "<code>1 d</code>" and not "<code>0 wk, 1 d, 0 hr, 0 min, 0 sec</code>").</li>
 
<li>Give larger units precedence over smaller ones as much as possible (e.g., return <code>2 min, 10 sec</code> and not <code>1 min, 70 sec</code> or <code>130 sec</code>)</li>
 
<li>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).</li>
</ul>
 
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).
<hr style="margin:1em 0;"/>
<br><br>
 
=={{header|11l}}==
{{trans|Julia}}
<syntaxhighlight lang="11l">F duration(=sec)
[Int] t
L(dm) [60, 60, 24, 7]
Int m
(sec, m) = (sec I/ dm, sec % dm)
t.insert(0, m)
t.insert(0, sec)
R zip(t, [‘wk’, ‘d’, ‘hr’, ‘min’, ‘sec’]).filter(num_unit -> num_unit[0] > 0).map(num_unit -> num_unit[0]‘ ’num_unit[1]).join(‘, ’)
 
print(duration(7259))
print(duration(86400))
print(duration(6000000))</syntaxhighlight>
 
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
{{libheader|Action! Real Math}}
<syntaxhighlight lang="action!">INCLUDE "H6:REALMATH.ACT"
DEFINE PTR="CARD"
 
TYPE Time=[BYTE s,m,h,d,w]
CARD ARRAY units(5)
 
PROC Convert(REAL POINTER seconds Time POINTER t)
BYTE ARRAY b,duration=[60 60 24 7]
BYTE i
REAL r,n
 
b=t
FOR i=0 TO 3
DO
IntToReal(duration(i),n)
RealMod(seconds,n,r)
b(i)=RealToInt(r)
RealDivInt(seconds,n,r)
RealAssign(r,seconds)
OD
b(4)=RealToInt(seconds)
RETURN
 
PROC PrintTime(Time POINTER t)
INT i
BYTE first,n
BYTE ARRAY b
 
b=t i=4 first=1
WHILE i>=0
DO
n=b(i)
IF n>0 THEN
IF first=0 THEN
Print(", ")
ELSE
first=0
FI
PrintF("%B %S",n,units(i))
FI
i==-1
OD
RETURN
 
PROC Test(CHAR ARRAY s)
REAL seconds
Time t
 
ValR(s,seconds)
PrintR(seconds) Print(" -> ")
Convert(seconds,t)
PrintTime(t) PutE()
RETURN
 
PROC Main()
Put(125) PutE() ;clear the screen
MathInit()
units(0)="sec" units(1)="min"
units(2)="hr" units(3)="d"
units(4)="wk"
Test("7259")
Test("86400")
Test("6000000")
RETURN
</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Convert_seconds_to_compound_duration.png Screenshot from Atari 8-bit computer]
<pre>
259 -> 2 hr, 59 sec
86400 -> 1 d
6000000 -> 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
 
procedure Convert is
Line 112 ⟶ 207:
IO.New_Line;
end loop;
end Convert;</langsyntaxhighlight>
 
{{out}}
Line 125 ⟶ 220:
6001230 SECONDS = 9 WK, 6 D, 11 HR, 30 SEC
600000000 SECONDS = 992 WK, 10 HR, 40 MIN</pre>
 
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68"># MODE to hold the compound duration #
MODE DURATION = STRUCT( INT weeks, days, hours, minutes, seconds );
 
Line 170 ⟶ 264:
print( ( TOSTRING TODURATION 7259, newline ) );
print( ( TOSTRING TODURATION 86400, newline ) );
print( ( TOSTRING TODURATION 6000000, newline ) )</langsyntaxhighlight>
{{out}}
<pre>
Line 178 ⟶ 272:
</pre>
 
=={{header|AppleScriptALGOL W}}==
Based on Algol 68 but Algol W does not have dynamic string handling which makes this more complex.
<syntaxhighlight lang="algolw">begin
% record structure to hold a compound duration %
record Duration ( integer weeks, days, hours, minutes, seconds );
 
% returns seconds converted to a Duration %
{{Trans|JavaScript}}
reference(Duration) procedure toDuration( integer value secs ) ;
begin
integer time;
reference(Duration) d;
time := secs;
d := Duration( 0, 0, 0, 0, 0 );
seconds(d) := time rem 60;
time := time div 60;
minutes(d) := time rem 60;
time := time div 60;
hours(d) := time rem 24;
time := time div 24;
days(d) := time rem 7;
time := time div 7;
weeks(d) := time;
d
end toDuration ;
 
% returns a readable form of the DURATION %
<lang AppleScript>on run
string(80) procedure durationToString ( reference(Duration) value d ) ;
intercalate(linefeed, ¬
begin
map(test, ¬
% appends an element of the compound duration to text %
[7259, 86400, 6000000]))
procedure add ( integer value componentValue
end run
; string(6) value componentName
; integer value nameLength
) ;
begin
string(9) vStr;
integer v, vPos;
if needSeparator then begin
% must separate this component from the previous %
text( textPos // 2 ) := ", ";
textPos:= textPos + 2
end if_needSepartator ;
% add the value %
% construct a string representaton of the value with the digits reversed %
% as this routine isn't called if componentValue is 0 or -ve, we don't need to handle %
% the componentVaue <= 0 case %
v := componentValue;
vStr := "";
vPos := 0;
while v > 0 do begin
vStr( vPos // 1 ) := code( decode( "0" ) + ( v rem 10 ) );
vPos := vPos + 1;
v := v div 10
end while_v_gt_0 ;
% add the digits in the correct order %
while vPos > 0 do begin
vPos := vPos - 1;
text( textPos // 1 ) := vStr( vPos // 1 );
textPos := textPos + 1
end while_vPos_gt_0 ;
% add the component name %
text( textPos // 6 ) := componentName;
textPos := textPos + nameLength;
% if there is another component, we'll need a separator %
needSeparator := true
end add ;
 
string(80) text;
-- test :: Int -> String
logical needSeparator;
on test(intSeconds)
integer textPos;
(intSeconds as string) & " -> " & angloDuration(intSeconds)
textPos := 0;
end test
text := "";
needSeparator := false;
if weeks(d) not = 0 then add( weeks(d), " wk", 3 );
if days(d) not = 0 then add( days(d), " d", 2 );
if hours(d) not = 0 then add( hours(d), " hr", 3 );
if minutes(d) not = 0 then add( minutes(d), " min", 4 );
if seconds(d) not = 0 then add( seconds(d), " sec", 4 );
if text = "" then begin
% duration is 0 %
text := "0 sec"
end if_text_is_blank ;
text
end % durationToString % ;
 
% test cases %
write( durationToString( toDuration( 7259 ) ) );
write( durationToString( toDuration( 86400 ) ) );
write( durationToString( toDuration( 6000000 ) ) )
end.</syntaxhighlight>
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">duration←{
names←'wk' 'd' 'hr' 'min' 'sec'
parts←0 7 24 60 60⊤⍵
fmt←⍕¨(parts≠0)/parts,¨names
¯2↓∊fmt,¨⊂', '
}</syntaxhighlight>
{{out}}
<pre> duration 7259
2 hr, 59 sec
duration 86400
1 d
duration 6000000
9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|AppleScript}}==
-- DURATION STRINGS
===Functional===
<syntaxhighlight lang="applescript">
-------------------- COMPOUND DURATIONS ------------------
 
-- angloDuration ::weekParts Int -> String[Int]
on angloDurationweekParts(intSeconds)
unitParts(intSeconds, [missing value, 7, 24, 60, 60])
script mf
--end weekParts Int -> [Int]
 
on weekParts(intSeconds)
 
unitParts(intSeconds, [missing value, 7, 24, 60, 60])
-- localCompoundDuration :: Int -> String
end weekParts
on localCompoundDuration(localNames, intSeconds)
-- [String] -> (Int, String) -> [String]
-- [String] -> (Int, String) -> [String]
on formatted(a, lstPair)
script formatted
on |λ|(lstPair, a)
set q to item 1 of lstPair
if q > 0 then
Line 213 ⟶ 407:
a
end if
end formatted|λ|
end script
intercalate(", ", ¬
foldr(formatted of mf, [], ¬
zip(weekParts(intSeconds) of mf, ¬localNames)))
end localCompoundDuration
["wk", "d", "hr", "min", "sec"])))
end angloDuration
 
------------------ INTEGER DECOMPOSITION -----------------
 
-- INTEGER DECOMPOSITION
 
-- unitParts :: Int -> [maybe Int] -> [Int]
on unitParts(intTotal, unitList)
-- partList :: Record -> Int -> Record
script mf
--script partList Record -> Int -> Record
on partList|λ|(ax, xa)
set intRest to remaining of a
Line 241 ⟶ 433:
{remaining:(intRest - intMod) div d, parts:{intMod} & parts of a}
end partList|λ|
end script
parts of foldr(partList of mf, ¬
{remaining:intTotal, parts:[]}, unitList)
end unitParts
 
--------------------------- TEST -------------------------
on run
script angloNames
on |λ|(n)
(n as string) & " -> " & ¬
localCompoundDuration(["wk", "d", "hr", "min", "sec"], n)
end |λ|
end script
unlines(map(angloNames, [7259, 86400, 6000000]))
end run
 
 
-------------------- GENERIC FUNCTIONS -------------------
 
-- foldr :: (a -> b -> ab) -> ab -> [ba] -> ab
on foldr(f, startValue, xs)
set mf totell mReturn(f)
set v to startValue
set vlng to startValuelength of xs
set repeat with i from lng to length1 ofby xs-1
repeat with i from lng set v to 1|λ|(item byi of xs, v, i, -1xs)
end repeat
set v to mf's lambda(v, item i of xs, i, xs)
end repeat return v
returnend vtell
end foldr
 
 
-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, delim}
set s to xs as text
set my text item delimiters to dlm
s
end intercalate
 
 
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
set mf to mReturn(f)
set lng-- to lengtheach element of xs.
settell lst to {}mReturn(f)
repeat with i from 1set lng to lnglength of xs
set end of lst to mf's lambda(item i of xs, i, xs){}
end repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
return lst
end repeat
return lst
end tell
end map
 
 
-- zip :: [a] -> [b] -> [(a, b)]
-- min :: Ord a => a -> a -> a
on zip(xs, ys)
on min(x, y)
script mf
if y < on pair(x, i)then
y
[x, item i of my closure's ys]
end pair
end script
if length of xs = length of ys then
map(mClosure(pair of mf, {ys:ys}), xs)
else
missing valuex
end if
end zipmin
 
-- intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate
 
 
 
-- LiftmReturn 2nd:: First-class handlerm function=> into(a 1st-> classb) -> m script(a wrapper-> b)
-- mReturn :: Handler -> Script
on mReturn(f)
if-- 2nd class ofhandler ffunction islifted scriptinto then1st class script returnwrapper. f
if script is class of f then
property lambda : f
end scriptelse
script
property |λ| : f
end script
end if
end mReturn
 
-- mClosure :: Handler -> Record -> Script
on mClosure(f, recBindings)
script
property closure : recBindings
property lambda : f
end script
end mClosure
</lang>
 
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
 
 
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
-- A list of step-wise pairs drawn from xs and ys
-- up to the length of the shorter of those lists.
set lng to min(length of xs, length of ys)
set zs to {}
repeat with i from 1 to lng
set end of zs to {item i of xs, item i of ys}
end repeat
return zs
end zip</syntaxhighlight>
{{Out}}
<pre>7259 -> 2 hr, 59 sec
86400 -> 1 d
6000000 -> 9 wk, 6 d, 10 hr, 40 min</pre>
 
----
===Straightforward===
<syntaxhighlight lang="applescript">on secondsToCompoundDuration(sec)
if ((sec's class is not integer) or (sec < 0)) then ¬
error "secondsToCompoundDuration() handler only accepts positive integers."
-- The task description notwithstanding, return "0 sec" if the input is 0.
if (sec = 0) then return "0 sec"
-- Otherwise perform the described task.
set units to {weeks, days, hours, minutes, 1}
set suffixes to {" wk, ", " d, ", " hr, ", " min, ", " sec, "}
set output to ""
repeat with i from 1 to 5
set unit to units's item i
set unitValue to sec div unit
if (unitValue > 0) then set output to output & unitValue & suffixes's item i
set sec to sec mod unit
if (sec = 0) then exit repeat
end repeat
return output's text 1 thru -3
end secondsToCompoundDuration
 
return secondsToCompoundDuration(7259) & linefeed & ¬
secondsToCompoundDuration(86400) & linefeed & ¬
secondsToCompoundDuration(6000000)</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">"2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min"</syntaxhighlight>
 
=={{header|Applesoft BASIC}}==
<syntaxhighlight lang="applesoftbasic">100 DATA604800,WK,86400,D,3600,HR,60,MIN,1,SEC
110 FOR I = 0 TO 4
120 READ M(I), U$(I)
130 NEXT
140 DATA7259,86400,6000000
150 ON ERR GOTO 270
160 READ S
170 GOSUB 200
180 PRINT S " = " S$
190 GOTO 160
 
200 N = S
210 S$ = ""
220 FOR I = 0 TO 4
230 IF INT(N / M(I)) THEN S$ = S$ + MID$(", ", 1, (LEN(S$) > 0) * 2) + STR$(INT(N / M(I))) + " " + U$(I)
240 N = N - INT(N / M(I)) * M(I)
250 NEXT I
260 RETURN
 
270 END
</syntaxhighlight>
 
=={{header|Arturo}}==
{{trans|Nim}}
<syntaxhighlight lang="rebol">Units: [" wk", " d", " hr", " min", " sec"]
Quantities: @[7 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1]
durationString: function [d][
dur: d
idx: 0
result: new []
while [not? zero? dur][
q: dur / Quantities\[idx]
if not? zero? q [
dur: dur % Quantities\[idx]
'result ++ ~{|q||Units\[idx]|}
]
idx: idx +1
]
return join.with:", " result
]
 
loop [7259 86400 6000000] 't [
print [t "s => " durationString t]
]</syntaxhighlight>
 
{{out}}
 
<pre>7259 s => 2 hr, 59 sec
86400 s => 1 d
6000000 s => 9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">duration(n){
sec:=1, min:=60*sec, hr:=60*min, day:=24*hr, wk:=7*day
w :=n//wk , n:=Mod(n,wk)
Line 332 ⟶ 638:
s :=n
return trim((w?w " wk, ":"") (d?d " d, ":"") (h?h " hr, ":"") (m?m " min, ":"") (s?s " sec":""),", ")
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">data=
(
7259
Line 343 ⟶ 649:
res .= A_LoopField "`t: " duration(A_LoopField) "`n"
MsgBox % res
return</langsyntaxhighlight>
Outputs:<pre>7259 : 2 hr, 59 sec
86400 : 1 d
Line 349 ⟶ 655:
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f CONVERT_SECONDS_TO_COMPOUND_DURATION.AWK
BEGIN {
Line 384 ⟶ 690:
return(str)
}
</syntaxhighlight>
</lang>
<p>Output:</p>
<pre>
Line 398 ⟶ 704:
694861 1 wk, 1 d, 1 hr, 1 min, 1 sec
</pre>
 
=={{header|BASIC}}==
 
==={{header|Commodore BASIC}}===
<syntaxhighlight lang="gwbasic">10 REM CONVERT SECONDS TO COMPOUND DURATION
20 REM ADAPTED FROM RUN BASIC VERSION
30 REM ===============================================================
40 PRINT CHR$(14)
50 SEC = 7259
60 GOSUB 1000
70 SEC = 85400
80 GOSUB 1000
90 SEC = 6000000
100 GOSUB 1000
110 END
120 REM ==============================================================
1000 WK = INT(SEC/60/60/24/7)
1010 DY = INT(SEC/60/60/24) - 7*WK
1020 HR = INT(SEC/60/60) - 24*(DY+7*WK)
1030 MN = INT(SEC/60) - 60*(HR+24*(DY+7*WK))
1040 SC = SEC - 60*(MN+60*(HR+24*(DY+7*WK)))
1050 PRINT SEC;"SEC" : PRINT " =";
1055 F = 0
1060 IF WK = 0 THEN 1080
1070 PRINT WK;"WK"; : F = 1
1080 IF DY = 0 THEN 1110
1090 IF F THEN PRINT ",";
1100 PRINT DY;"DY"; : F = 1
1110 IF HR = 0 THEN 1140
1120 IF F THEN PRINT ",";
1130 PRINT HR;"HR"; : F = 1
1140 IF MN = 0 THEN 1170
1150 IF F THEN PRINT ",";
1160 PRINT MN;"MIN"; : F = 1
1170 IF (SC > 0) AND F THEN PRINT ",";SC;"SEC" : GOTO 1200
1180 IF (SC = 0) AND F THEN 1200
1190 PRINT SC;"SEC"
1200 PRINT
1210 RETURN</syntaxhighlight>
{{out}}
7259 sec
= 2 hr, 59 sec
85400 sec
= 23 hr, 43 min, 20 sec
6000000 sec
= 9 wk, 6 dy, 10 hr, 40 min
 
==={{header|BaCon}}===
<syntaxhighlight lang="freebasic">
'--- SAY_TIME Convert seconds to compound duration
'--- Weeks, days hours, minutes ,seconds
SUB SAY_TIME(int sec)
 
LOCAL week,day,hour,minute,second TYPE int
week = sec / 604800
day = MOD(sec /86400,7)
hour = MOD(sec / 3600 ,24)
minute = MOD(sec / 60 ,60)
second = MOD(sec,60)
IF week > 0 THEN
PRINT STR$(week) & " wk, " TO p1$ SIZE 100
END IF
 
IF day > 0 THEN
PRINT STR$(day) & " d, " TO p2$ SIZE 100
END IF
 
IF hour > 0 THEN
PRINT STR$(hour) & " h, " TO p3$ SIZE 100
END IF
 
IF minute > 0 THEN
PRINT STR$(minute) & " min, " TO p4$ SIZE 100
END IF
 
IF second > 0 THEN
PRINT STR$(second) & " sec " TO p5$ SIZE 100
END IF
 
 
PRINT p1$ ,p2$, p3$, p4$, p5$
END SUB
 
'---result 9 wk, 6 d, 10 h, 40 min, 7 sec
SAY_TIME(6000007)
</syntaxhighlight>
==={{header|BBC BASIC}}===
<syntaxhighlight lang="bbcbasic">REM >compduration
PRINT FN_convert(7259)
PRINT FN_convert(86400)
PRINT FN_convert(6000000)
END
:
DEF FN_convert(seconds%)
LOCAL units%(), units$(), i%, unit%, compound$
DIM units%(4)
DIM units$(4)
units%() = 604800, 86400, 3600, 60, 1
units$() = "wk", "d", "hr", "min", "sec"
compound$ = ""
FOR i% = 0 TO 4
IF seconds% >= units%(i%) THEN
unit% = seconds% DIV units%(i%)
seconds% = seconds% MOD units%(i%)
compound$ += STR$(unit%) + " " + units$(i%)
IF i% < 4 AND seconds% > 0 THEN compound$ += ", "
ENDIF
NEXT
= compound$</syntaxhighlight>
{{out}}
<pre>2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min</pre>
 
==={{header|IS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "Seconds.bas"
110 NUMERIC UN(1 TO 5),SEC,UNIT
120 STRING T$(1 TO 5)*3
130 LET UN(1)=604800:LET UN(2)=86400:LET UN(3)=3600:LET UN(4)=60:LET UN(5)=1
140 LET T$(1)="wk":LET T$(2)="d":LET T$(3)="hr":LET T$(4)="min":LET T$(5)="sec"
150 INPUT PROMPT "Duration in seconds: ":SEC
160 PRINT SEC;"sec =";
170 FOR I=1 TO 5
180 IF SEC>=UN(I) THEN
190 LET UNIT=INT(SEC/UN(I)):LET SEC=MOD(SEC,UN(I))
200 PRINT UNIT;T$(I);
210 IF I<4 AND SEC>0 THEN PRINT ",";
220 END IF
230 NEXT
240 PRINT</syntaxhighlight>
 
=={{header|Batch File}}==
<langsyntaxhighlight lang="dos">@echo off
::The Main Thing...
for %%d in (7259 86400 6000000) do call :duration %%d
Line 425 ⟶ 866:
if %1 gtr 0 echo %1 sec = %output:~1,-1%
goto :EOF
::/The Function.</langsyntaxhighlight>
{{Out}}
<pre>
Line 435 ⟶ 876:
=={{header|beeswax}}==
 
<langsyntaxhighlight lang="beeswax">#>%f# #>%f# #f%<##>%f#
pq":X~7~ :X@~++8~8@:X:X@~-~4~.+~8@T_
## ## #### #`K0[`}`D2[`}BF3< <
>{` wk, `>g?"p{` d, `>g?"p{` hr, `>g?"p{` min, `>g"b{` sec, `b
> d > d > d > d</langsyntaxhighlight>
 
{{Out}}
Line 462 ⟶ 903:
The value to convert is read from stdin, and the corresponding compound duration is written to stdout.
 
<langsyntaxhighlight lang="befunge">&>:"<"%\"O{rq"**+\"<"/:"<"%\"r<|":*+*5-\v
v-7*"l~"/7\"d"\%7:/*83\+*:"xD"\%*83:/"<"<
> \:! #v_v#-#<",",#$48*#<,#<.#<>#_:"~"%,v
^_@#:$$< > .02g92p ^ ^!:/"~"<</langsyntaxhighlight>
 
{{out}}
Line 476 ⟶ 917:
 
=={{header|C}}==
 
<lang c>
===C: Version written in C89. Average skill level.===
<syntaxhighlight lang="c">/*
* Program seconds2string, C89 version.
*
* Read input from argv[1] or stdin, write output to stdout.
*/
 
#define _CRT_SECURE_NO_WARNINGS /* unlocks printf in Microsoft Visual Studio */
 
#include <stdio.h>
#include <stdlib.h>
 
/*
* Converting the number of seconds in a human-readable string.
* It is worth noting that direct output to stdout would be even simpler.
*/
char* seconds2string(unsigned long seconds)
{
int i;
 
const unsigned long s = 1;
const unsigned long m = 60 * s;
const unsigned long h = 60 * m;
const unsigned long d = 24 * h;
const unsigned long w = 7 * d;
 
const unsigned long coeff[5] = { w, d, h, m, s };
const char units[5][4] = { "wk", "d", "hr", "min", "sec" };
 
static char buffer[256];
char* ptr = buffer;
 
for ( i = 0; i < 5; i++ )
{
unsigned long value;
value = seconds / coeff[i];
seconds = seconds % coeff[i];
if ( value )
{
if ( ptr != buffer )
ptr += sprintf(ptr, ", ");
ptr += sprintf(ptr,"%lu %s",value,units[i]);
}
}
 
return buffer;
}
 
/*
* Main function for seconds2string program.
*/
int main(int argc, char argv[])
{
unsigned long seconds;
 
if ( (argc < 2) && scanf( "%lu", &seconds )
|| (argc >= 2) && sscanf( argv[1], "%lu", & seconds ) )
{
printf( "%s\n", seconds2string(seconds) );
return EXIT_SUCCESS;
}
 
return EXIT_FAILURE;
}</syntaxhighlight>
 
===C: Version written in C99. Low skill level.===
<syntaxhighlight lang="c">
#include <inttypes.h> /* requires c99 */
#include <stdbool.h> /* requires c99 */
Line 617 ⟶ 1,125:
return minutes*60;
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 631 ⟶ 1,139:
</pre>
 
=={{header|C sharp|C#}}==
 
===C#: Standard method===
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 685 ⟶ 1,193:
}
}</langsyntaxhighlight>
 
{{out}}
Line 701 ⟶ 1,209:
{{libheader|System.Linq}}
{{works with|C sharp|6}}
<langsyntaxhighlight lang="csharp">private static string ConvertToCompoundDuration(int seconds)
{
if (seconds < 0) throw new ArgumentOutOfRangeException(nameof(seconds));
Line 714 ⟶ 1,222:
where parts[index] > 0
select parts[index] + units[index]);
}</langsyntaxhighlight>
 
=={{header|C++}}==
{{works with|C++11}}
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <vector>
Line 754 ⟶ 1,262:
std::cout << " 86400 sec is "; print(convert( 86400));
std::cout << "6000000 sec is "; print(convert(6000000));
}</langsyntaxhighlight>
{{out}}
<pre>
Line 761 ⟶ 1,269:
6000000 sec is 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(require '[clojure.string :as string])
 
(def seconds-in-minute 60)
(def seconds-in-hour (* 60 seconds-in-minute))
(def seconds-in-day (* 24 seconds-in-hour))
(def seconds-in-week (* 7 seconds-in-day))
 
(defn seconds->duration [seconds]
(let [weeks ((juxt quot rem) seconds seconds-in-week)
wk (first weeks)
days ((juxt quot rem) (last weeks) seconds-in-day)
d (first days)
hours ((juxt quot rem) (last days) seconds-in-hour)
hr (first hours)
min (quot (last hours) seconds-in-minute)
sec (rem (last hours) seconds-in-minute)]
(string/join ", "
(filter #(not (string/blank? %))
(conj []
(when (> wk 0) (str wk " wk"))
(when (> d 0) (str d " d"))
(when (> hr 0) (str hr " hr"))
(when (> min 0) (str min " min"))
(when (> sec 0) (str sec " sec")))))))
 
(seconds->duration 7259)
(seconds->duration 86400)
(seconds->duration 6000000)</syntaxhighlight>
 
{{out}}
<pre>
"2 hr, 59 sec"
"1 d"
"9 wk, 6 d, 10 hr, 40 min"
</pre>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">duration = proc (s: int) returns (string)
own units: array[string] := array[string]$["wk","d","hr","min","sec"]
own sizes: array[int] := array[int]$[2:7,24,60,60]
d: string := ""
r: int
for i: int in int$from_to_by(5,1,-1) do
begin
r := s // sizes[i]
s := s / sizes[i]
end except when bounds:
r := s
end
if r ~= 0 then
d := ", " || int$unparse(r) || " " || units[i] || d
end
end
return(string$rest(d,3))
end duration
 
start_up = proc ()
po: stream := stream$primary_output()
tests: array[int] := array[int]$[7259,86400,6000000]
for test: int in array[int]$elements(tests) do
stream$putl(po, int$unparse(test) || " => " || duration(test))
end
end start_up</syntaxhighlight>
{{out}}
<pre>7259 => 2 hr, 59 sec
86400 => 1 d
6000000 => 9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|COBOL}}==
<langsyntaxhighlight COBOLlang="cobol"> identification division.
program-id. fmt-dura.
data division.
Line 836 ⟶ 1,415:
.
end program fmt.
end program fmt-dura.</langsyntaxhighlight>
<pre>Enter duration (seconds): 7259
2 hr, 59 sec
Line 843 ⟶ 1,422:
Enter duration (seconds): 6000000
9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">(defconstant +seconds-in-minute* 60)
(defconstant +seconds-in-hour* (* 60 +seconds-in-minute*))
(defconstant +seconds-in-day* (* 24 +seconds-in-hour*))
(defconstant +seconds-in-week* (* 7 +seconds-in-day*))
 
(defun seconds->duration (seconds)
(multiple-value-bind (weeks wk-remainder) (floor seconds +seconds-in-week*)
(multiple-value-bind (days d-remainder) (floor wk-remainder +seconds-in-day*)
(multiple-value-bind (hours hr-remainder) (floor d-remainder +seconds-in-hour*)
(multiple-value-bind (minutes secs) (floor hr-remainder +seconds-in-minute*)
(let ((chunks nil))
(unless (zerop secs) (push (format nil "~D sec" secs) chunks))
(unless (zerop minutes) (push (format nil "~D min" minutes) chunks))
(unless (zerop hours) (push (format nil "~D hr" hours) chunks))
(unless (zerop days) (push (format nil "~D d" days) chunks))
(unless (zerop weeks) (push (format nil "~D wk" weeks) chunks))
(format t "~{~A~^, ~}~%" chunks)))))))
 
(seconds->duration 7259)
(seconds->duration 86400)
(seconds->duration 6000000)
</syntaxhighlight>
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|D}}==
<syntaxhighlight lang="d">
<lang d>
import std.stdio, std.conv, std.algorithm;
 
Line 885 ⟶ 1,494:
6_000_000.ConvertSeconds.writeln;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls,DateUtils}}
 
 
<syntaxhighlight lang="Delphi">
const TestData: array [0..2] of integer = (7259,86400,6000000);
 
function SecondsToFormatDate(Sec: integer): string;
var DT: TDateTime;
var Weeks: integer;
var AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word;
const SecPerDay = 60 * 60 * 24;
begin
{Convert seconds to Delphi TDateTime}
{which is floating point days}
DT:=Sec / SecPerDay;
{Get weeks and subtract them off}
Weeks:=Trunc(DT/7);
DT:=DT - Weeks * 7;
{Decode date}
DecodeDateTime(DT,AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond);
{Compensate because TDateTime starts on Dec 30th 1899}
if aDay<30 then aDay:=aDay + 1 else aDay:=aDay - 30;
Result:='';
if Weeks<>0 then Result:=Result+IntToStr(Weeks)+' wk, ';
if ADay<>0 then Result:=Result+IntToStr(ADay)+' d, ';
if AHour<>0 then Result:=Result+IntToStr(AHour)+' hr, ';
if AMinute<>0 then Result:=Result+IntToStr(AMinute)+' min, ';
if ASecond<>0 then Result:=Result+IntToStr(ASecond)+' sec, ';
end;
 
procedure ShowFormatedDataTime(Memo: TMemo);
var I: integer;
begin
for I:=0 to High(TestData) do
Memo.Lines.Add(IntToStr(TestData[I])+' = '+SecondsToFormatDate(TestData[I]));
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
7259 = 2 hr, 59 sec,
86400 = 1 d,
6000000 = 9 wk, 6 d, 10 hr, 40 min,
Elapsed Time: 2.900 ms.
 
</pre>
 
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
func$ split sec .
divs[] = [ 60 60 24 7 ]
n$[] = [ "sec" "min" "hr" "d" "wk" ]
len r[] 5
for i = 1 to 4
r[i] = sec mod divs[i]
sec = sec div divs[i]
.
r[5] = sec
for i = 5 downto 1
if r[i] <> 0
if s$ <> ""
s$ &= ", "
.
s$ &= r[i] & " " & n$[i]
.
.
return s$
.
print split 7259
print split 86400
print split 6000000
</syntaxhighlight>
 
{{out}}
<pre>
Line 894 ⟶ 1,587:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">defmodule Convert do
@minute 60
@hour @minute*60
Line 914 ⟶ 1,607:
Enum.each([7259, 86400, 6000000], fn sec ->
:io.fwrite "~10w sec : ~s~n", [sec, Convert.sec_to_str(sec)]
end)</langsyntaxhighlight>
 
{{out}}
Line 930 ⟶ 1,623:
Function ''intercalate/2'' is copied from [https://github.com/tim/erlang-oauth/blob/master/src/oauth.erl a Tim Fletcher's GitHub repository].
 
<langsyntaxhighlight lang="erlang">
-module(convert_seconds).
 
Line 1,020 ⟶ 1,713:
 
% **************************************************
</syntaxhighlight>
</lang>
 
Output:
Line 1,030 ⟶ 1,723:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
 
let convert seconds =
Line 1,050 ⟶ 1,743:
|> Seq.map (fun str -> let sec = UInt32.Parse str in (sec, convert sec))
|> Seq.iter (fun (s, v) -> printfn "%10i = %s" s v)
0</langsyntaxhighlight>
{{out}}
<pre>>RosettaCode 7259 86400 6000000
Line 1,056 ⟶ 1,749:
86400 = 1 day
6000000 = 9 wk, 6 day, 10 hr, 40 min</pre>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: assocs io kernel math math.parser qw sequences
sequences.generalizations ;
 
: mod/ ( x y -- w z ) /mod swap ;
 
: convert ( n -- seq )
60 mod/ 60 mod/ 24 mod/ 7 mod/ 5 narray reverse ;
: .time ( n -- )
convert [ number>string ] map qw{ wk d hr min sec } zip
[ first "0" = ] reject [ " " join ] map ", " join print ;
7259 86400 6000000 [ .time ] tri@</syntaxhighlight>
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Forth}}==
{{works with|Gforth|0.7.3}}
<syntaxhighlight lang="forth">CREATE C 0 ,
: ., C @ IF ." , " THEN 1 C ! ;
: .TIME ( n --)
[ 60 60 24 7 * * * ]L /MOD ?DUP-IF ., . ." wk" THEN
[ 60 60 24 * * ]L /MOD ?DUP-IF ., . ." d" THEN
[ 60 60 * ]L /MOD ?DUP-IF ., . ." hr" THEN
[ 60 ]L /MOD ?DUP-IF ., . ." min" THEN
?DUP-IF ., . ." sec" THEN 0 C ! ;</syntaxhighlight>
{{out}}
<pre>2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|Fortran}}==
Line 1,061 ⟶ 1,790:
 
If the time to describe was not an integer but a floating-point value with fractional parts, then there is a complication. The number of seconds can be less than sixty, but, on output, 60 seconds can appear. If the number of seconds was to be written with one decimal digit (say) and the output format was F4.1 for that, then if the value was 59·95 or more, it will be rounded up for output, in this example to 60·0. Various systems make this mistake, as also with latitude and longitude, and it is a general problem. A fixup pass is necessary before generating the output: maintain an array with the integer values of the various units, then (for one decimal digit usage) check that the seconds part is less than 59·95. If not, set it to zero and augment the minutes count. If this is 60 or more, set it to zero and augment the hours count, and so on. Thus the array.
<syntaxhighlight lang="fortran">
<lang Fortran>
SUBROUTINE PROUST(T) !Remembrance of time passed.
INTEGER T !The time, in seconds. Positive only, please.
Line 1,099 ⟶ 1,828:
CALL PROUST(-666)
END
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,108 ⟶ 1,837:
0 ><
-666 ><
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">'FreeBASIC version 1.05 32/64 bit
 
Sub Show(m As Long)
Dim As Long c(1 To 5)={604800,86400,3600,60,1}
Dim As String g(1 To 5)={" Wk"," d"," hr"," min"," sec"},comma
Dim As Long b(1 To 5),flag,m2=m
Redim As Long s(0)
For n As Long=1 To 5
If m>=c(n) Then
Do
Redim Preserve s(Ubound(s)+1)
s(Ubound(s))=c(n)
m=m-c(n)
Loop Until m<c(n)
End If
Next n
For n As Long=1 To Ubound(s)
For m As Long=1 To 5
If s(n)=c(m) Then b(m)+=1
Next m
Next n
Print m2;" seconds = ";
For n As Long=1 To 5
If b(n) Then: comma=Iif(n<5 Andalso b(n+1),","," and"):flag+=1
If flag=1 Then comma=""
Print comma;b(n);g(n);
End If
Next
Print
End Sub
 
#define seconds
 
Show 7259 seconds
Show 86400 seconds
Show 6000000 seconds
sleep</syntaxhighlight>
Output:
<pre>
7259 seconds = 2 hr and 59 sec
86400 seconds = 1 d
6000000 seconds = 9 Wk, 6 d, 10 hr and 40 min
</pre>
 
=={{header|Frink}}==
Frink's <CODE>-&gt;</CODE> operator can break a unit of measure into its constituent parts. However, it does not suppress zero-valued elements unless they are at the beginning or the end, so we have to do that manually.
 
<syntaxhighlight lang="frink">
wk := week
n = eval[input["Enter duration in seconds: "]]
res = n s -> [0, "wk", "d", "hr", "min", "sec", 0]
res =~ %s/, 0[^,]+//g
println[res]
</syntaxhighlight>
 
=={{header|FutureBasic}}==
{{trans|C}}
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
local fn CompoundDurationString( seconds as long ) as CFStringRef
long s = 1, m = s * 60, h = m * 60, d = h * 24, w = d * 7
long v(4) : v(0) = w : v(1) = d : v(2) = h : v(3) = m : v(4) = s
long i, value
CFArrayRef abbr = @[@"wk",@"d",@"hr",@"min",@"sec"]
CFMutableStringRef string = fn MutableStringWithCapacity(0)
for i = 0 to 4
value = seconds / v(i)
seconds = seconds mod v(i)
if ( value )
if ( len(string) ) then MutableStringAppendString( string, @", " )
MutableStringAppendFormat( string, @"%ld %@", value, abbr[i] )
end if
next
end fn = string
 
NSLog(@"%@",fn CompoundDurationString(7259))
NSLog(@"%@",fn CompoundDurationString(86400))
NSLog(@"%@",fn CompoundDurationString(6000000))
 
HandleEvents
</syntaxhighlight>
 
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=d7f00b8a96a6f792f0164f622f0686df Click this link to run this code]'''
<syntaxhighlight lang="gambas">Public Sub Main()
Dim iInput As Integer[] = [7259, 86400, 6000000] 'Input details
Dim iChecks As Integer[] = [604800, 86400, 3600, 60] 'Weeks, days, hours, mins in seconds
Dim iTime As New Integer[5] 'To store wk, d, hr, min & sec
Dim iOriginal, iSec, iLoop As Integer 'Various integers
Dim sOrd As String[] = [" wk", " d", " hr", " min", " sec"] 'To add to the output string
Dim sOutput As String 'Output string
 
For Each iSec In iInput 'For each iInput
iOriginal = iSec 'Store orginal value in seconds
iTime[4] = iSec 'Store seconds in iTime[4]
 
For iLoop = 0 To 3 'Loop through wk, d, hr, min & sec
If iTime[4] >= iChecks[iLoop] Then 'Check if value is = to wk, d, hr, min
iTime[iLoop] = Int(iTime[4] / iChecks[iLoop]) 'Put the correct value for wk, d, hr, min in iTime
iTime[4] = iTime[4] - (iTime[iLoop] * iChecks[iLoop]) 'Remove the amount of seconds for wk, d, hr, min from iTime[4]
Endif
Next
 
For iLoop = 0 To 4 'Loop through wk, d, hr, min & secs
If iTime[iLoop] > 0 Then sOutput &= ", " & Str(iTime[iLoop]) & sOrd[iLoop] 'Add comma and ordinal as needed
Next
 
If Left(sOutput, 2) = ", " Then sOutput = Mid(sOutput, 3) 'Remove unnecessary ", "
sOutput = Format(Str(iOriginal), "#######") & " Seconds = " & sOutput 'Add original seconds to the output string
Print sOutput 'Print sOutput string
sOutput = "" 'Clear the sOutput string
iTime = New Integer[5] 'Reset iTime[]
Next
 
End</syntaxhighlight>
Output:
<pre>
7259 Seconds = 2 hr, 59 sec
86400 Seconds = 1 d
6000000 Seconds = 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Go}}==
<syntaxhighlight lang="go">package main
 
import "fmt"
 
func main(){
fmt.Println(TimeStr(7259))
fmt.Println(TimeStr(86400))
fmt.Println(TimeStr(6000000))
}
 
func TimeStr(sec int)(res string){
wks, sec := sec / 604800,sec % 604800
ds, sec := sec / 86400, sec % 86400
hrs, sec := sec / 3600, sec % 3600
mins, sec := sec / 60, sec % 60
CommaRequired := false
if wks != 0 {
res += fmt.Sprintf("%d wk",wks)
CommaRequired = true
}
if ds != 0 {
if CommaRequired {
res += ", "
}
res += fmt.Sprintf("%d d",ds)
CommaRequired = true
}
if hrs != 0 {
if CommaRequired {
res += ", "
}
res += fmt.Sprintf("%d hr",hrs)
CommaRequired = true
}
if mins != 0 {
if CommaRequired {
res += ", "
}
res += fmt.Sprintf("%d min",mins)
CommaRequired = true
}
if sec != 0 {
if CommaRequired {
res += ", "
}
res += fmt.Sprintf("%d sec",sec)
}
return
}
</syntaxhighlight>
{{Out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Control.Monad (forM_)
import Data.List (intercalate, mapAccumR)
import System.Environment (getArgs)
Line 1,138 ⟶ 2,057:
forM_ args $ \arg -> case readMaybe arg of
Just n -> printf "%7d seconds = %s\n" n (compoundDuration n)
Nothing -> putStrLn $ "Invalid number of seconds: " ++ arg</langsyntaxhighlight>
 
{{out}}
Line 1,146 ⟶ 2,065:
6000000 seconds = 9 wk, 6 d, 10 hr, 40 min
</pre>
 
 
Or, parameterising both the local names for these durations, and also the working assumptions about hours per day, and days per week:
 
<syntaxhighlight lang="haskell">import Data.List (intercalate, mapAccumR)
 
---------------- COMPOUND DURATION STRINGS ---------------
 
durationString ::
String ->
String ->
Int ->
Int ->
[String] ->
Int ->
String
durationString
componentGap
numberLabelGap
daysPerWeek
hoursPerDay
xs
n =
intercalate
componentGap
( foldr
(timeTags numberLabelGap)
[]
(zip (weekParts daysPerWeek hoursPerDay n) xs)
)
 
timeTags :: String -> (Int, String) -> [String] -> [String]
timeTags numberLabelGap (n, s) xs
| 0 < n = intercalate numberLabelGap [show n, s] : xs
| otherwise = xs
 
weekParts :: Int -> Int -> Int -> [Int]
weekParts daysPerWeek hoursPerDay =
snd
. flip
(mapAccumR byUnits)
[0, daysPerWeek, hoursPerDay, 60, 60]
 
byUnits :: Int -> Int -> (Int, Int)
byUnits rest x = (quot (rest - m) u, m)
where
(u, m)
| 0 < x = (x, rem rest x)
| otherwise = (1, rest)
 
--------------------------- TEST -------------------------
 
translation :: String -> Int -> Int -> Int -> String
translation local daysPerWeek hoursPerDay n =
intercalate " -> " $
[ show,
durationString
", "
" "
daysPerWeek
hoursPerDay
(words local)
]
<*> [n]
 
main :: IO ()
main = do
let names = "wk d hr min sec"
let tests = [7259, 86400, 6000000]
 
putStrLn "Assuming 24 hrs per day:"
mapM_ (putStrLn . translation names 7 24) tests
 
putStrLn "\nor, at 8 hours per day, 5 days per week:"
mapM_ (putStrLn . translation names 5 8) tests</syntaxhighlight>
{{Out}}
<pre>Assuming 24/7:
7259 -> 2 hr, 59 sec
86400 -> 1 d
6000000 -> 9 wk, 6 d, 10 hr, 40 min
 
or, at 8 working hours per day, 5 days per week:
7259 -> 2 hr, 59 sec
86400 -> 3 d
6000000 -> 41 wk, 3 d, 2 hr, 40 min</pre>
 
=={{header|J}}==
Line 1,151 ⟶ 2,155:
Implementation:
 
<langsyntaxhighlight Jlang="j">fmtsecs=: verb define
seq=. 0 7 24 60 60 #: y
}: ;:inv ,(0 ~: seq) # (8!:0 seq) ,. <;.2'wk,d,hr,min,sec,'
)</langsyntaxhighlight>
 
The first line uses integer division with remainder to break the value in seconds into its components (weeks, days, hours, minutes, seconds).
 
The second line gives each value a label and a trailing comma, drops the parts which have a zero, combines the rest and then removes the trailing comma from the end of the resulting line.
 
Task examples:
 
<langsyntaxhighlight Jlang="j"> fmtsecs 7259
2 hr, 59 sec
fmtsecs 86400
1 d
fmtsecs 6000000
9 wk, 6 d, 10 hr, 40 min</langsyntaxhighlight>
 
=={{header|Jakt}}==
<syntaxhighlight lang="jakt">
fn main() {
for seconds in [
7259
86400
6000000
] {
println("{}", time_string(seconds))
}
}
 
fn time_string(mut seconds: i64) throws -> String {
mut result = ""
 
mut minutes = seconds / 60
seconds %= 60
if seconds > 0 {
result = format("{} sec", seconds, result)
}
 
mut hours = minutes / 60
minutes %= 60
if minutes > 0 {
result = format(match result {
"" => "{} min"
else => "{} min, {}"
}, minutes, result)
}
 
mut days = hours / 24
hours %= 24
if hours > 0 {
result = format(match result {
"" => "{} hr"
else => "{} hr, {}"
}, hours, result)
}
 
mut weeks = days / 7
days %= 7
if days > 0 {
result = format(match result {
"" => "{} d"
else => "{} d, {}"
}, days, result)
}
if weeks > 0 {
result = format(match result {
"" => "{} wk"
else => "{} wk, {}"
}, weeks, result)
}
 
return result
}
</syntaxhighlight>
 
=={{header|Java}}==
This is a relatively simple task in Java, using the modulus-remainder operator.
<lang java>public class CompoundDuration {
<syntaxhighlight lang="java">
String duration(int seconds) {
StringBuilder string = new StringBuilder();
if (seconds >= 604_800 /* 1 wk */) {
string.append("%,d wk".formatted(seconds / 604_800));
seconds %= 604_800;
}
if (seconds >= 86_400 /* 1 d */) {
if (!string.isEmpty()) string.append(", ");
string.append("%d d".formatted(seconds / 86_400));
seconds %= 86_400;
}
if (seconds >= 3600 /* 1 hr */) {
if (!string.isEmpty()) string.append(", ");
string.append("%d hr".formatted(seconds / 3600));
seconds %= 3600;
}
if (seconds >= 60 /* 1 min */) {
if (!string.isEmpty()) string.append(", ");
string.append("%d min".formatted(seconds / 60));
seconds %= 60;
}
if (seconds > 0) {
if (!string.isEmpty()) string.append(", ");
string.append("%d sec".formatted(seconds));
}
return string.toString();
}
</syntaxhighlight>
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
<br />
An alternate demonstration
<syntaxhighlight lang="java">public class CompoundDuration {
 
public static void main(String[] args) {
Line 1,196 ⟶ 2,299:
return sec;
}
}</langsyntaxhighlight>
 
<pre>2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min</pre>
 
 
=={{header|JavaScript}}==
Line 1,209 ⟶ 2,311:
====ES5====
 
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
 
Line 1,268 ⟶ 2,370:
 
})();
</syntaxhighlight>
</lang>
 
{{Out}}
Line 1,277 ⟶ 2,379:
 
====ES6====
<syntaxhighlight lang="javascript">(() => {
"use strict";
 
// ---------------- COMPOUND DURATION ----------------
<lang JavaScript>(() => {
 
// angloDurationcompoundDuration :: [String] -> Int -> String
const compoundDuration = labels =>
function angloDuration(intSeconds) {
returnnSeconds => weekParts(intSecondsnSeconds)
.map((v, i) => [v, ["wk", "d", "hr", "min","sec"]labels[i]])
.reduce((a, x) =>
a.concat(x[0] ? [`${x[0]} ${x[1]}`] : []),
x[0] ? [
) `${x[0]} ${x[1] || "?"}`
.join(', '); ] : []
} ), []
)
.join(", ");
 
 
// weekParts :: Int -> [Int]
letconst weekParts = intSecondsnSeconds => [undefined0, 7, 24, 60, 60]
.reduceRight((a, x) => {
let r = a.rem,const
modr = isNaN(x) ? r : r % x;a[0],
mod = x !== 0 ? r % x : r;
 
return {[
rem: (r - mod) / (x || 1),
parts: [mod], .concat(a.parts).a[1]]
}];
}, {[nSeconds, []])[1];
rem: intSeconds,
parts: []
})
.parts;
 
 
// ---------------------- TEST -----------------------
// TEST
return// [7259,main 86400,:: 6E6]IO ()
const main = .map(intSeconds) => {
const localNames = ["wk", "d", "hr", "min", "sec"];
`${intSeconds} -> ${angloDuration(intSeconds)}`
)
.join("\n");
 
})();</lang>
 
return [7259, 86400, 6E6]
.map(nSeconds =>
`${nSeconds} -> ${
compoundDuration(localNames)(nSeconds)
}`).join("\n");
};
 
// MAIN ---
return main();
})();</syntaxhighlight>
{{Out}}
<pre>7259 -> 2 hr, 59 sec
Line 1,326 ⟶ 2,434:
=={{header|jq}}==
{{works with|jq|1.4}}
'''Also works with gojq, the Go implementation'''
<lang jq>def seconds_to_time_string:
<syntaxhighlight lang="jq">def seconds_to_time_string:
def nonzero(text): floor | if . > 0 then "\(.) \(text)" else empty end;
if . == 0 then "0 sec"
Line 1,336 ⟶ 2,445:
(. % 60 | nonzero("sec"))]
| join(", ")
end;</langsyntaxhighlight>
 
''Examples''':
<langsyntaxhighlight lang="jq">0, 7259, 86400, 6000000 | "\(.): \(seconds_to_time_string)"</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -r -n -f Convert_seconds_to_compound_duration.jq
0: 0 sec
7259: 2 hr, 59 sec
86400: 1 d
6000000: 9 wk, 6 d, 10 hr, 40 min</langsyntaxhighlight>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia"># 1.x
function duration(sec::Integer)::String
t = Array{Int}([])
for dm in (60, 60, 24, 7)
sec, m = divrem(sec, dm)
pushfirst!(t, m)
end
pushfirst!(t, sec)
return join(["$num$unit" for (num, unit) in zip(t, ["w", "d", "h", "m", "s"]) if num > 0], ", ")
end
 
@show duration(7259)
@show duration(86400)
@show duration(6000000)
</syntaxhighlight>
 
{{out}}
<pre>
duration(7259) = "2h, 59s"
duration(86400) = "1d"
duration(6000000) = "9w, 6d, 10h, 40m"
</pre>
 
=={{header|K}}==
{{works with|ngn/k}}<syntaxhighlight lang=K>F:{", "/" "/'+($x[s]),s:,&0<x}(" "\"wk d hr min sec")!0 7 24 60 60\</syntaxhighlight>
 
Examples:
 
<syntaxhighlight lang=K>F 100
"1 min, 40 sec"
F 7259
"2 hr, 59 sec"
F 86400
"1 d"
F 6000000
"9 wk, 6 d, 10 hr, 40 min"</syntaxhighlight>
 
tested in ngn/k
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">fun compoundDuration(n: Int): String {
if (n < 0) return "" // task doesn't ask for negative integers to be converted
if (n == 0) return "0 sec"
val weeks : Int
val days : Int
val hours : Int
val minutes: Int
val seconds: Int
var divisor: Int = 7 * 24 * 60 * 60
var rem : Int
var result = ""
 
weeks = n / divisor
rem = n % divisor
divisor /= 7
days = rem / divisor
rem %= divisor
divisor /= 24
hours = rem / divisor
rem %= divisor
divisor /= 60
minutes = rem / divisor
seconds = rem % divisor
 
if (weeks > 0) result += "$weeks wk, "
if (days > 0) result += "$days d, "
if (hours > 0) result += "$hours hr, "
if (minutes > 0) result += "$minutes min, "
if (seconds > 0)
result += "$seconds sec"
else
result = result.substring(0, result.length - 2)
return result
}
 
fun main(args: Array<String>) {
val durations = intArrayOf(0, 7, 84, 7259, 86400, 6000000)
durations.forEach { println("$it\t-> ${compoundDuration(it)}") }
}</syntaxhighlight>
 
{{out}}
<pre>
0 -> 0 sec
7 -> 7 sec
84 -> 1 min, 24 sec
7259 -> 2 hr, 59 sec
86400 -> 1 d
6000000 -> 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|langur}}==
<syntaxhighlight lang="langur">val .duration = fn(var .sec) {
[
fw/wk d hr min sec/,
for[=[]] .dm in [7 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60] {
_for ~= [.sec \ .dm]
.sec rem= .dm
} ~ [.sec],
]
}
 
for .seconds in [7259, 86400, 6000000] {
val .dur = .duration(.seconds)
write $"\.seconds:7; sec = "
writeln join ", ", for[=[]] .k of .dur[1] {
if .dur[2][.k] != 0: _for ~= [$"\.dur[2][.k]; \.dur[1][.k];"]
}
}
</syntaxhighlight>
 
{{out}}
<pre> 7259 sec = 2 hr, 59 sec
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Liberty BASIC}}==
I got a bit carried away and added 'years'...
<syntaxhighlight lang="lb">
<lang lb>
[start]
input "Enter SECONDS: "; seconds
Line 1,356 ⟶ 2,582:
UnitsFound=0: LastFound$=""
years=int(seconds/31449600): seconds=seconds mod 31449600
if years then UnitsFound+=1: LastFound$="years"
weeks=int(seconds/604800): seconds=seconds mod 604800
if weeks then UnitsFound+=1: LastFound$="weeks"
days=int(seconds/86400): seconds=seconds mod 86400
if days then UnitsFound+=1: LastFound$="days"
hours=int(seconds/3600): seconds=seconds mod 3600
if hours then UnitsFound+=1: LastFound$="hours"
minutes=int(seconds/60): seconds=seconds mod 60
if minutes then UnitsFound+=1: LastFound$="minutes"
if seconds then UnitsFound+=1: LastFound$="seconds"
select case years
case 0
Line 1,438 ⟶ 2,664:
print
goto [start]
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,454 ⟶ 2,680:
 
=={{header|Lua}}==
<langsyntaxhighlight Lualang="lua">function duration (secs)
local units, dur = {"wk", "d", "hr", "min"}, ""
for i, v in ipairs({604800, 86400, 3600, 60}) do
Line 1,471 ⟶ 2,697:
print(duration(7259))
print(duration(86400))
print(duration(6000000))</langsyntaxhighlight>
 
=={{header|MathematicaMaple}}==
<syntaxhighlight lang="maple">
<lang Mathematica>
tim := proc (s) local weeks, days, hours, minutes, seconds;
compoundDuration[x_Integer] :=
weeks := trunc((1/604800)*s);
days := trunc((1/86400)*s)-7*weeks;
hours := trunc((1/3600)*s)-24*days-168*weeks;
minutes := trunc((1/60)*s)-60*hours-1440*days-10080*weeks;
seconds := s-60*minutes-3600*hours-86400*days-604800*weeks;
printf("%s", cat(`if`(0 < weeks, cat(weeks, "wk, "), NULL), `if`(0 < days, cat(days, "d, "), NULL), `if`(0 < hours, cat(hours, "hr, "), NULL), `if`(0 < minutes, cat(minutes, "min, "), NULL), `if`(0 < seconds, cat(seconds, "sec"), NULL)))
end proc;
</syntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">compoundDuration[x_Integer] :=
StringJoin @@ (Riffle[
ToString /@ ((({Floor[x/604800],
Line 1,486 ⟶ 2,723:
Grid[Table[{n, "secs =",
compoundDuration[n]}, {n, {7259, 86400, 6000000}}],
Alignment -> {Left, Baseline}]</syntaxhighlight>
 
</lang>
 
{{out}}
<pre>7259 secs = 2 hr, 59 sec
<pre>
7259 secs = 2 hr, 59 sec
86400 secs = 1 d,
6000000 secs = 9 wk, 6 d, 10 hr, 40 min, </pre>
 
</pre>
=={{header|Nim}}==
<syntaxhighlight lang="nim">from strutils import addSep
 
const
Units = [" wk", " d", " hr", " min", " sec"]
Quantities = [7 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1]
 
#---------------------------------------------------------------------------------------------------
 
proc `$$`*(sec: int): string =
## Convert a duration in seconds to a friendly string.
 
doAssert(sec > 0)
 
var duration = sec
var idx = 0
while duration != 0:
let q = duration div Quantities[idx]
if q != 0:
duration = duration mod Quantities[idx]
result.addSep(", ", 0)
result.add($q & Units[idx])
inc idx
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
when isMainModule:
for sec in [7259, 86400, 6000000]:
echo sec, "s = ", $$sec</syntaxhighlight>
 
{{out}}
<pre>7259s = 2 hr, 59 sec
86400s = 1 d
6000000s = 9 wk, 6 d, 10 hr, 40 min</pre>
 
===Using the “times” module===
 
It is also possible to use the Duration type in the “times” module and the procedure “toParts” which decomposes a duration in units of time (nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days and weeks).
 
<syntaxhighlight lang="nim">import times
from algorithm import reversed
from strutils import addSep
 
const Units = [" wk", " d", " hr", " min", " sec"]
 
#---------------------------------------------------------------------------------------------------
 
proc `$$`*(sec: int): string =
## Convert a duration in seconds to a friendly string.
## Similar to `$` but with other conventions.
 
doAssert(sec > 0)
 
var duration = initDuration(seconds = sec)
let parts = reversed(duration.toParts[Seconds..Weeks])
 
for idx, part in parts:
if part != 0:
result.addSep(", ", 0)
result.add($part & Units[idx])
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
when isMainModule:
for sec in [7259, 86400, 6000000]:
echo sec, "s = ", $$sec</syntaxhighlight>
 
{{out}}
 
Output is the same.
 
=={{header|OCaml}}==
{{works with|OCaml|4.03+}}
<syntaxhighlight lang="ocaml">let divisors = [
(max_int, "wk"); (* many wk = many wk *)
(7, "d"); (* 7 d = 1 wk *)
(24, "hr"); (* 24 hr = 1 d *)
(60, "min"); (* 60 min = 1 hr *)
(60, "sec") (* 60 sec = 1 min *)
]
 
 
(* Convert a number of seconds into a list of values for weeks, days, hours,
* minutes and seconds, by dividing the number of seconds 'secs' successively by
* the values contained in the list 'divisors' (taking them in reverse order).
* Ex:
* compute_duration 7259
* returns
* [(0, "wk"); (0, "d"); (2, "hr") (0, "min"); (59, "sec")]
*)
let compute_duration secs =
let rec doloop remain res = function
| [] -> res
| (n, s) :: ds -> doloop (remain / n) ((remain mod n, s) :: res) ds
in
doloop secs [] (List.rev divisors)
 
 
(* Format nicely the list of values.
* Ex:
* pretty_print [(0, "wk"); (0, "d"); (2, "hr") (0, "min"); (59, "sec")]
* returns
* "2 hr, 59 sec"
*
* Intermediate steps:
* 1. Keep only the pairs where duration is not 0
* [(2, "hr"); (59, "sec")]
* 2. Format each pair as a string
* ["2 hr"; "59 sec"]
* 3. Concatenate the strings separating them by a comma+space
* "2 hr, 59 sec"
*)
let pretty_print dur =
List.filter (fun (d, _) -> d <> 0) dur
|> List.map (fun (d, l) -> Printf.sprintf "%d %s" d l)
|> String.concat ", "
 
 
(* Transform a number of seconds into the corresponding compound duration
* string.
* Not sure what to do with 0... *)
let compound = function
| n when n > 0 -> compute_duration n |> pretty_print
| n when n = 0 -> string_of_int 0 ^ "..."
| _ -> invalid_arg "Number of seconds must be positive"
 
 
(* Some testing... *)
let () =
let test_cases = [
(7259, "2 hr, 59 sec");
(86400, "1 d");
(6000000, "9 wk, 6 d, 10 hr, 40 min");
(0, "0...");
(3599, "59 min, 59 sec");
(3600, "1 hr");
(3601, "1 hr, 1 sec")
] in
let testit (n, s) =
let calc = compound n in
Printf.printf "[%s] %d seconds -> %s; expected: %s\n"
(if calc = s then "PASS" else "FAIL")
n calc s
in
List.iter testit test_cases</syntaxhighlight>
{{out}}
[PASS] 7259 seconds -> 2 hr, 59 sec; expected: 2 hr, 59 sec
[PASS] 86400 seconds -> 1 d; expected: 1 d
[PASS] 6000000 seconds -> 9 wk, 6 d, 10 hr, 40 min; expected: 9 wk, 6 d, 10 hr, 40 min
[PASS] 0 seconds -> 0...; expected: 0...
[PASS] 3599 seconds -> 59 min, 59 sec; expected: 59 min, 59 sec
[PASS] 3600 seconds -> 1 hr; expected: 1 hr
[PASS] 3601 seconds -> 1 hr, 1 sec; expected: 1 hr, 1 sec
 
=={{header|PARI/GP}}==
Line 1,502 ⟶ 2,889:
{{Works with|PARI/GP|2.7.4 and above}}
 
<langsyntaxhighlight lang="parigp">
\\ Convert seconds to compound duration
\\ 4/11/16 aev
Line 1,519 ⟶ 2,906:
print(secs2compdur(6000000));
}
</langsyntaxhighlight>
 
{{Output}}
Line 1,528 ⟶ 2,915:
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Pascal}}==
{{works with|Extended Pascal}}
<syntaxhighlight lang="pascal">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.</syntaxhighlight>
{{out}}
7259 seconds are “2 hr, 59 sec”
86400 seconds are “1 d”
6000000 seconds are “9 wk, 6 d, 10 hr, 40 min”
 
=={{header|Perl}}==
 
===Direct calculation===
<lang perl>sub compound_duration {
<syntaxhighlight lang="perl">use strict;
use warnings;
 
sub compound_duration {
my $sec = shift;
no warnings 'numeric';
Line 1,541 ⟶ 3,054:
int($sec/60) % 60 . " min",
int($sec) % 60 . " sec";
}
}</lang>
 
for (7259, 86400, 6000000) {
Demonstration:
<lang perl>for (7259, 86400, 6000000) {
printf "%7d sec = %s\n", $_, compound_duration($_)
}</langsyntaxhighlight>
 
{{out}}
<pre> 7259 sec = 2 hr, 59 sec
<pre>
7259 sec = 2 hr, 59 sec
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min</pre>
</pre>
 
===Using polymod===
=={{header|Perl 6}}==
More general approach for mixed-radix conversions.
<syntaxhighlight lang="perl">use strict;
use warnings;
use Math::AnyNum 'polymod';
 
sub compound_duration {
The built-in <code>polymod</code> method (which is a generalization of the <code>divmod</code> function known from other languages), is a perfect match for a task like this:
my $seconds = shift;
my @terms;
 
my @durations = reverse polymod($seconds, 60, 60, 24, 7);
<lang perl6>sub compound-duration ($seconds) {
($seconds.polymod(60,my 60,@timespans 24, 7) Z= <secwk mind hr dmin wksec>);
while (my $d = shift @durations, my $t = shift @timespans) {
.grep(*[0]).reverse.join(", ")
push @terms, "$d $t" if $d
}</lang>
}
 
join ', ', @terms
Demonstration:
}
<lang perl6>for 7259, 86400, 6000000 {
say "{.fmt: '%7d'} sec = {compound-duration $_}";
}</lang>
 
for (<7259 86400 6000000 3380521>) {
printf "%7d sec = %s\n", $_, compound_duration($_)
}</syntaxhighlight>
{{out}}
<pre> 7259 sec = 2 hr, 59 sec
<pre>
7259 sec = 2 hr, 59 sec
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
3380521 sec = 5 wk, 4 d, 3 hr, 2 min, 1 sec</pre>
</pre>
 
=={{header|Phix}}==
TheThere existingis a standard function for this, for more details see builtins/pelapsed.e (which will be kept up to date, unlike giveshaving thea resultscopy shownhere)
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>?elapsed(7259)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
?elapsed(86400)
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7259</span><span style="color: #0000FF;">)</span>
?elapsed(6000000)</lang>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">86400</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">6000000</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
"2 hours and 59s"
"1 day, 0 hours"
"699 weeks, 6 days, 10 hours, 40 minutes"
</pre>
You may also be interested in the timedelta() function, which converts durations to seconds, eg:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">timedate</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">6000000</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">timedelta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">days</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hours</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">10</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
"9 weeks, 40 minutes"
</pre>
The routine is implemented in builtins\pelapsed.e which you can modify as desired, and is reproduced for reference below
<lang Phix>function elapzd(integer v, string d)
-- private helper function. formats v and pluralises d by adding an "s", or not.
return sprintf("%d %s%s",{v,d,iff(v=1?"":"s")})
end function
 
=={{header|PicoLisp}}==
global function elapsed(atom s)
<syntaxhighlight lang="picolisp">(for Sec (7259 86400 6000000)
-- convert s (in seconds) into an elapsed time string suitable for display.
(tab (-10 -30)
-- limits: a type check error occurs if s exceeds approx 100 billion years.
Sec
atom m,h,d,y
(glue ", "
string minus = "", secs, mins
if s<0 then (extract
minus = "minus " '((N Str)
s = 0-s (when (gt0 (/ Sec N))
(setq Sec (% Sec N))
end if
(pack @ " " Str) ) )
m = floor(s/60)
s = remainder (s,604800 86400 3600 60 1)
'("wk" "d" "hr" "min" "sec") ) ) ) )</syntaxhighlight>
secs = sprintf(iff(integer(s)?"%ds":"%3.2fs"),s)
Output:
if m=0 then
<pre>7259 2 hr, 59 sec
return sprintf("%s%s",{minus,secs})
86400 end if1 d
6000000 9 wk, 6 d, 10 hr, 40 min</pre>
s = round(s)
secs = iff(s=0?"":sprintf(" and %02ds",s))
h = floor(m/60)
m = remainder(m,60)
if h=0 then
return sprintf("%s%s%s",{minus,elapzd(m,"minute"),secs})
end if
mins = iff(m=0?"":", "&elapzd(m,"minute"))
if h<24 then
return sprintf("%s%s%s%s",{minus,elapzd(h,"hour"),mins,secs})
end if
d = floor(h/24)
h = remainder(h,24)
if d<365 then
return sprintf("%s%s, %s%s%s",{minus,elapzd(d,"day"),elapzd(h,"hour"),mins,secs})
end if
y = floor(d/365)
d = remainder(d,365)
return sprintf("%s%s, %s, %s%s%s",{minus,elapzd(y,"year"),elapzd(d,"day"),elapzd(h,"hour"),mins,secs})
end function</lang>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
/* Convert seconds to Compound Duration (weeks, days, hours, minutes, seconds). */
 
Line 1,658 ⟶ 3,162:
end;
end cvt;
</syntaxhighlight>
</lang>
Results:
<pre>
Line 1,674 ⟶ 3,178:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-Time
{
Line 1,791 ⟶ 3,295:
}
}
</syntaxhighlight>
</lang>
 
{{Out}}
Line 1,821 ⟶ 3,325:
TotalSeconds : 6000000
TotalMilliseconds : 6000000000
</pre>
 
=={{header|Prolog}}==
Works with Swi-Prolog.
Use Contraints for this task so the that functionality can be reversed (eg: find the number of seconds for a split date).
 
See below for examples.
 
<syntaxhighlight lang="prolog">:- use_module(library(clpfd)).
 
% helper to perform the operation with just a number.
compound_time(N) :-
times(N, R),
format('~p: ', N),
write_times(R).
 
% write out the results in the 'special' format.
write_times([[Tt, Val]|T]) :-
dif(T, []),
format('~w ~w, ', [Val, Tt]),
write_times(T).
write_times([[Tt, Val]|[]]) :-
format('~w ~w~n', [Val, Tt]).
 
 
% this predicate is the main predicate, it takes either N
% or a list of split values to get N, or both.
times(N, R) :-
findall(T, time_type(T,_), TTs),
times(TTs, N, R).
 
% do the split, if there is a 1 or greater add to a list of results.
times([], _, []).
times([Tt|T], N, Rest) :-
time_type(Tt, Div),
Val #= N // Div,
Val #< 1,
times(T, N, Rest).
times([Tt|T], N, [[Tt,Val]|Rest]) :-
time_type(Tt, Div),
Val #= N // Div,
Val #>= 1,
Rem #= N mod Div,
times(T, Rem, Rest).
 
 
% specifify the different time split types
time_type(wk, 60 * 60 * 24 * 7).
time_type(d, 60 * 60 * 24).
time_type(hr, 60 * 60).
time_type(min, 60).
time_type(sec, 1).</syntaxhighlight>
 
{{out}}
<pre>
?- maplist(compound_time, [7259,86400,6000000]), !.
7259: 2 hr, 59 sec
86400: 1 d
6000000: 9 wk, 6 d, 10 hr, 40 min
true.
 
?- times(N, [[wk, 9],[d, 6],[hr,10],[min,40]]), !.
N = 6000000.
</pre>
 
=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">
EnableExplicit
 
Procedure.s ConvertSeconds(NbSeconds)
Protected weeks, days, hours, minutes, seconds
Protected divisor, remainder
Protected duration$ = ""
divisor = 7 * 24 * 60 * 60 ; seconds in a week
weeks = NbSeconds / divisor
remainder = NbSeconds % divisor
divisor / 7 ; seconds in a day
days = remainder / divisor
remainder % divisor
divisor / 24 ; seconds in an hour
hours = remainder / divisor
remainder % divisor
divisor / 60 ; seconds in a minute
minutes = remainder / divisor
seconds = remainder % divisor
If weeks > 0
duration$ + Str(weeks) + " wk, "
EndIf
If days > 0
duration$ + Str(days) + " d, "
EndIf
If hours > 0
duration$ + Str(hours) + " hr, "
EndIf
If minutes > 0
duration$ + Str(minutes) + " min, "
EndIf
If seconds > 0
duration$ + Str(seconds) + " sec"
EndIf
If Right(duration$, 2) = ", "
duration$ = Mid(duration$, 0, Len(duration$) - 2)
EndIf
ProcedureReturn duration$
EndProcedure
 
If OpenConsole()
PrintN(ConvertSeconds(7259))
PrintN(ConvertSeconds(86400))
PrintN(ConvertSeconds(6000000))
PrintN("")
PrintN("Press any key to close the console")
Repeat: Delay(10) : Until Inkey() <> ""
CloseConsole()
EndIf
</syntaxhighlight>
 
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
Line 1,826 ⟶ 3,459:
 
===Python: Procedural===
<langsyntaxhighlight lang="python">>>> def duration(seconds):
t= []
for dm in (60, 60, 24, 7):
Line 1,843 ⟶ 3,476:
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
>>> </langsyntaxhighlight>
 
===Python: Functional===
<langsyntaxhighlight lang="python">>>> def duration(seconds, _maxweeks=99999999999):
return ', '.join('%d %s' % (num, unit)
for num, unit in zip([(seconds // d) % m
Line 1,862 ⟶ 3,495:
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
>>> </langsyntaxhighlight>
 
Or, composing a solution from pure curried functions, including the '''mapAccumR''' abstraction (a combination of of '''map''' and '''reduce''', implemented in a variety of languages and functional libraries, in which a new list is derived by repeated application of the same function, as an accumulator (here, a remainder) passes from right to left):
 
<syntaxhighlight lang="python">'''Compound duration'''
 
from functools import reduce
from itertools import chain
 
 
# compoundDurationFromUnits :: [Num] -> [String] -> Num -> [(Num, String)]
def compoundDurationFromUnits(qs):
'''A list of compound string representions of a number n of time units,
in terms of the multiples given in qs, and the labels given in ks.
'''
return lambda ks: lambda n: list(
chain.from_iterable(map(
lambda v, k: [(v, k)] if 0 < v else [],
mapAccumR(
lambda a, x: divmod(a, x) if 0 < x else (1, a)
)(n)(qs)[1],
ks
))
)
 
 
# --------------------------TEST---------------------------
# main :: IO ()
def main():
'''Tests of various durations, with a
particular set of units and labels.
'''
 
print(
fTable('Compound durations from numbers of seconds:\n')(str)(
quoted("'")
)(
lambda n: ', '.join([
str(v) + ' ' + k for v, k in
compoundDurationFromUnits([0, 7, 24, 60, 60])(
['wk', 'd', 'hr', 'min', 'sec']
)(n)
])
)([7259, 86400, 6000000])
)
 
 
# -------------------------GENERIC-------------------------
 
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> xs -> tabular string.
'''
def go(xShow, fxShow, f, xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
return s + '\n' + '\n'.join(map(
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
xs, ys
))
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
 
 
# mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumR(f):
'''A tuple of an accumulation and a list derived by a combined
map and fold, with accumulation from right to left.
'''
def go(a, x):
acc, y = f(a[0], x)
return (acc, [y] + a[1])
return lambda acc: lambda xs: (
reduce(go, reversed(xs), (acc, []))
)
 
 
# quoted :: Char -> String -> String
def quoted(c):
'''A string flanked on both sides
by a specified quote character.
'''
return lambda s: c + s + c
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>Compound durations from numbers of seconds:
 
7259 -> '2 hr, 59 sec'
86400 -> '1 d'
6000000 -> '9 wk, 6 d, 10 hr, 40 min'</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="quackery"> [ ' [ 60 60 24 7 ]
witheach [ /mod swap ]
$ ""
' [ $ " wk, " $ " d, "
$ " hr, " $ " min, "
$ " sec, " ]
witheach
[ do rot dup iff
[ number$
swap join join ]
else 2drop ]
-2 split drop ] is duration$ ( n--> $ )
 
' [ 7259 86400 6000000 ]
witheach
[ dup echo
say " seconds is "
duration$ echo$
say "." cr ]</syntaxhighlight>
 
{{Out}}
 
<pre>7259 seconds is 2 hr, 59 sec.
86400 seconds is 1 d.
6000000 seconds is 9 wk, 6 d, 10 hr, 40 min.
</pre>
 
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">#lang racket/base
(require racket/string
racket/list)
Line 1,897 ⟶ 3,656:
(check-equal? (seconds->compound-duration-string 6000000) "9 wk, 6 d, 10 hr, 40 min"))
 
;; Tim Brown 2015-07-21</langsyntaxhighlight>
 
{{out}}
All tests pass... there is no output.
 
=={{header|Raku}}==
(formerly Perl 6)
 
The built-in <code>polymod</code> method (which is a generalization of the <code>divmod</code> function known from other languages), is a perfect match for a task like this:
 
<syntaxhighlight lang="raku" line>sub compound-duration ($seconds) {
($seconds.polymod(60, 60, 24, 7) Z <sec min hr d wk>)
.grep(*[0]).reverse.join(", ")
}
 
# Demonstration:
 
for 7259, 86400, 6000000 {
say "{.fmt: '%7d'} sec = {compound-duration $_}";
}</syntaxhighlight>
 
{{out}}
<pre>
7259 sec = 2 hr, 59 sec
86400 sec = 1 d
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* Format seconds into a time string
*--------------------------------------------------------------------*/
Line 1,949 ⟶ 3,731:
a=what%how
b=what//how
Return a b</langsyntaxhighlight>
{{out}}
<pre>2 hr, 59 sec
Line 1,960 ⟶ 3,742:
===version 2===
This REXX version can also handle fractional (seconds) as well as values of zero (time units).
<langsyntaxhighlight lang="rexx">/*rexx program demonstrates how to convert a number of seconds to bigger time units.*/
parse arg @; if @='' then @=7259 86400 6000000 /*Not specified? Then use the default.*/
 
do j=1 for words(@); z= word(@, j) /* [↓] process each number in the list*/
say right(z, 25) 'seconds: ' convSec(z) /*convert a number to bigger time units*/
end /*j*/
Line 1,969 ⟶ 3,751:
/*──────────────────────────────────────────────────────────────────────────────────────*/
convSec: parse arg x /*obtain a number from the argument. */
w= timeU( 60*60*24*7, 'wk' ) /*obtain number of weeks (if any). */
d= timeU( 60*60*24 , 'd' ) /* " " " days " " */
h= timeU( 60*60 , 'hr' ) /* " " " hours " " */
m= timeU( 60 , 'min' ) /* " " " minutes " " */
s= timeU( 1 , 'sec' ) /* " " " seconds " " */
if x\==0 then s=word(s 0, 1) + x 'sec' /*handle fractional (residual) seconds.*/
$=strip(space(w d h m s),,","); if $=='' then z= 0 "sec" /*handle 0 sec.*/
return $
/*──────────────────────────────────────────────────────────────────────────────────────*/
timeU: parse arg u,$; _= x%u; if _==0 then return ''; x= x - _*u; return _ $","</langsyntaxhighlight>
'''{{out|output''' |text=&nbsp; when using the default (internal) inputs:}}
<pre>
7259 seconds: 2 hr, 59 sec
Line 1,985 ⟶ 3,767:
6000000 seconds: 9 wk, 6 d, 10 hr, 40 min
</pre>
'''{{out|output''' |text=&nbsp; when using the inputs: &nbsp; &nbsp; <tt> &nbsp; 1800.7 &nbsp; 123.50 &nbsp; 123.00 &nbsp; 0.00 </tt>}}
<pre>
1800.7 seconds: 30 min, 0.7 sec
Line 1,994 ⟶ 3,776:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
sec = 6000005
week = floor(sec/60/60/24/7)
Line 2,011 ⟶ 3,793:
if second > 0 see second
see " seconds" + nl ok
</syntaxhighlight>
</lang>
 
=={{header|RPL}}==
≪ MOD LAST / FLOOR ≫ '<span style="color:blue">'''DIVMOD'''</span>' STO
≪ {" wk" " d" " hr" " min" " sec" } → unit
≪ 60 <span style="color:blue">'''DIVMOD'''</span> 60 <span style="color:blue">'''DIVMOD'''</span> 24 <span style="color:blue">'''DIVMOD'''</span> 7 <span style="color:blue">'''DIVMOD'''</span>
1 SF ""
1 unit SIZE '''FOR''' j
'''IF''' SWAP '''THEN'''
LAST →STR unit j GET +
'''IF''' 1 FC?C '''THEN''' ", " SWAP + '''END'''
+ '''END'''
'''NEXT'''
≫ ≫ '<span style="color:blue">'''→CDUR'''</span>' STO
Users of HP-48G and newer models can replace the <code>60 <span style="color:blue">'''DIVMOD'''</span> 60 <span style="color:blue">'''DIVMOD'''</span> 24 <span style="color:blue">'''DIVMOD'''</span> 7 <span style="color:blue">'''DIVMOD'''</span></code> line by:
{ 60 60 24 7 } 1 ≪ MOD LAST / FLOOR ≫ DOSUBS OBJ→ DROP
 
7259 <span style="color:blue">'''→CDUR'''</span>
86400 <span style="color:blue">'''→CDUR'''</span>
6000000 <span style="color:blue">'''→CDUR'''</span>
10! <span style="color:blue">'''→CDUR'''</span>
{{out}}
<pre>
4: "2 hr, 59 sec"
3: "1 d"
2: "9 wk, 6 d, 10 hr, 40 min"
1: "6 wk"
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">MINUTE = 60
HOUR = MINUTE*60
DAY = HOUR*24
Line 2,028 ⟶ 3,838:
end
 
[7259, 86400, 6000000].each{|t| puts "#{t}\t: #{sec_to_str(t)}"}</langsyntaxhighlight>
Output:
<pre>
Line 2,037 ⟶ 3,847:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">sec = 6000005
week = int(sec/60/60/24/7)
day = int(sec/60/60/24) mod 7
Line 2,049 ⟶ 3,859:
if hour > 0 then print hour;" hours ";
if minute > 0 then print minute;" minutes ";
if second > 0 then print second;" seconds"</langsyntaxhighlight>
 
=={{header|Rust}}==
This solution deviates from the prompt a bit in order to make it more general. The benefit of doing it this way is that any values can be filled in for days, hours, minutes and seconds and the `balance` method will do the balancing accordingly. Also, rather than converting the value into a String, it simply implements the `Display` trait.
<langsyntaxhighlight lang="rust">use std::fmt;
 
 
Line 2,098 ⟶ 3,908:
ct.balance();
println!("After: {}", ct);
}</langsyntaxhighlight>
 
=={{header|Scala}}==
<syntaxhighlight lang="scala">//Converting Seconds to Compound Duration
 
object seconds{
def main( args:Array[String] ){
println("Enter the no.")
val input = scala.io.StdIn.readInt()
var week_r:Int = input % 604800
var week:Int = (input - week_r)/604800
var day_r:Int = week_r % 86400
var day:Int = (week_r - day_r)/86400
var hour_r:Int = day_r % 3600
var hour:Int = (day_r - hour_r)/3600
var minute_r:Int = hour_r % 60
var minute:Int = (hour_r - minute_r)/60
var sec:Int = minute_r % 60
println("Week = " + week)
println("Day = " + day)
println("Hour = " + hour)
println("Minute = " + minute)
println("Second = " + sec)
}
}</syntaxhighlight>
 
=={{header|Scheme}}==
 
{{libheader|Scheme/SRFIs}}
 
This version uses delete from SRFI 1 and string-join from SRFI 13:
 
<syntaxhighlight lang="scheme">
(import (scheme base)
(scheme write)
(srfi 1)
(only (srfi 13) string-join))
 
(define *seconds-in-minute* 60)
(define *seconds-in-hour* (* 60 *seconds-in-minute*))
(define *seconds-in-day* (* 24 *seconds-in-hour*))
(define *seconds-in-week* (* 7 *seconds-in-day*))
 
(define (seconds->duration seconds)
(define (format val unit)
(if (zero? val) "" (string-append (number->string val) " " unit)))
(let*-values (((weeks wk-remainder) (floor/ seconds *seconds-in-week*))
((days dy-remainder) (floor/ wk-remainder *seconds-in-day*))
((hours hr-remainder) (floor/ dy-remainder *seconds-in-hour*))
((minutes mn-remainder) (floor/ hr-remainder *seconds-in-minute*)))
(string-join (delete ""
(list (format weeks "wk")
(format days "d")
(format hours "hr")
(format minutes "min")
(format mn-remainder "sec"))
string=?) ", ")))
 
(display (seconds->duration 7259)) (newline)
(display (seconds->duration 86400)) (newline)
(display (seconds->duration 6000000)) (newline)
</syntaxhighlight>
 
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func polymod(n, *divs) {
gather {
divs.each { |i|
Line 2,120 ⟶ 4,005:
[7259, 86400, 6000000].each { |s|
say "#{'%7d' % s} sec = #{compound_duration(s)}"
}</langsyntaxhighlight>
 
{{out}}
Line 2,128 ⟶ 4,013:
6000000 sec = 9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">local
fun fmtNonZero (0, _, list) = list
| fmtNonZero (n, s, list) = Int.toString n ^ " " ^ s :: list
fun divModHead (_, []) = []
| divModHead (d, head :: tail) = head div d :: head mod d :: tail
in
fun compoundDuration seconds =
let
val digits = foldl divModHead [seconds] [60, 60, 24, 7]
and units = ["wk", "d", "hr", "min", "sec"]
in
String.concatWith ", " (ListPair.foldr fmtNonZero [] (digits, units))
end
end
 
val () = app (fn s => print (compoundDuration s ^ "\n")) [7259, 86400, 6000000]</syntaxhighlight>
 
=={{header|Swift}}==
<syntaxhighlight lang="swift">func duration (_ secs:Int) -> String {
if secs <= 0 { return "" }
let units = [(604800,"wk"), (86400,"d"), (3600,"hr"), (60,"min")]
var secs = secs
var result = ""
for (period, unit) in units {
if secs >= period {
result += "\(secs/period) \(unit), "
secs = secs % period
}
}
if secs == 0 {
result.removeLast(2) // remove ", "
} else {
result += "\(secs) sec"
}
return result
}
print(duration(7259))
print(duration(86400))
print(duration(6000000))</syntaxhighlight>
 
=={{header|Tcl}}==
Line 2,133 ⟶ 4,060:
The data-driven procedure below can be customised to use different breakpoints, simply by editing the dictionary.
 
<langsyntaxhighlight Tcllang="tcl">proc sec2str {i} {
set factors {
sec 60
Line 2,170 ⟶ 4,097:
check {sec2str 7259} {2 hr, 59 sec}
check {sec2str 86400} {1 d}
check {sec2str 6000000} {9 wk, 6 d, 10 hr, 40 min}</langsyntaxhighlight>
 
{{Out}}
Line 2,179 ⟶ 4,106:
=={{header|uBasic/4tH}}==
Since uBasic/4tH is integer-only, it is hard to return a string. However, it is capable to transform an integer value as required.
<syntaxhighlight lang="text">Proc _CompoundDuration(7259)
Proc _CompoundDuration(86400)
Proc _CompoundDuration(6000000)
Line 2,217 ⟶ 4,144:
_d Print " d"; : Return
_hr Print " hr"; : Return
_min Print " min"; : Return</langsyntaxhighlight>
{{out}}
<pre>2 hr, 59 sec
Line 2,224 ⟶ 4,151:
 
0 OK, 0:94</pre>
 
=={{header|Vale}}==
{{works with|Vale|0.2.0}}
<syntaxhighlight lang="vale">
import stdlib.*;
import stdlib.stdin.*;
import stdlib.math.*;
 
exported func main() {
foreach testCase in [#][
7259,
86400,
6000000,
] {
testCase.timeString().println();
}
}
 
func timeString(seconds int) str {
result = "";
 
minutes = seconds / 60;
set seconds = seconds.mod(60);
if seconds > 0 {
set result = seconds.str() + " sec";
}
 
hours = minutes / 60;
set minutes = minutes.mod(60);
if minutes > 0 {
set result = minutes.str() + if result != "" {
" min, " + result
} else {
" min"
};
}
 
days = hours / 24;
set hours = hours.mod(24);
if hours > 0 {
set result = hours.str() + if result != "" {
" hr, " + result
} else {
" hr"
};
}
 
weeks = days / 7;
set days = days.mod(7);
if days > 0 {
set result = days.str() + if result != "" {
" d, " + result
} else {
" d"
};
}
if weeks > 0 {
set result = weeks.str() + if result != "" {
" wk, " + result
} else {
" wk"
};
}
 
return result;
}
</syntaxhighlight>
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">Private Function compound_duration(ByVal seconds As Long) As String
minutes = 60
hours = 60 * minutes
days_ = 24 * hours
weeks = 7 * days_
Dim out As String
w = seconds \ weeks
seconds = seconds - w * weeks
d = seconds \ days_
seconds = seconds - d * days_
h = seconds \ hours
seconds = seconds - h * hours
m = seconds \ minutes
s = seconds Mod minutes
out = IIf(w > 0, w & " wk, ", "") & _
IIf(d > 0, d & " d, ", "") & _
IIf(h > 0, h & " hr, ", "") & _
IIf(m > 0, m & " min, ", "") & _
IIf(s > 0, s & " sec", "")
If Right(out, 2) = ", " Then
compound_duration = Left(out, Len(out) - 2)
Else
compound_duration = out
End If
End Function
 
Public Sub cstcd()
Debug.Print compound_duration(7259)
Debug.Print compound_duration(86400)
Debug.Print compound_duration(6000000)
End Sub</syntaxhighlight>{{out}}
<pre>2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min</pre>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
<lang vb>
Function compound_duration(n)
Do Until n = 0
Line 2,264 ⟶ 4,294:
WScript.StdOut.WriteLine compound_duration(86400)
WScript.StdOut.WriteLine compound_duration(6000000)
</syntaxhighlight>
</lang>
 
{{Out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|Wren}}==
<syntaxhighlight lang="wren">var duration = Fn.new { |s|
if (s < 1) return "0 sec"
var dur = ""
var divs = [7, 24, 60, 60, 1]
var units = ["wk", "d", "hr", "min", "sec"]
var t = divs.reduce { |prod, div| prod * div }
for (i in 0...divs.count) {
var u = (s/t).floor
if (u > 0) {
dur = dur + "%(u) %(units[i]), "
s = s % t
}
t = t / divs[i]
}
if (dur.endsWith(", ")) dur = dur[0..-3]
return dur
}
 
for (s in [7259, 86400, 6000000]) System.print(duration.call(s))</syntaxhighlight>
 
{{out}}
<pre>
2 hr, 59 sec
1 d
9 wk, 6 d, 10 hr, 40 min
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">char Str(80);
func Duration(Sec); \Convert seconds to compound duration
int Sec, Amt, Unit, DoComma, I, Quot;
[Amt:= [7*24*60*60, 24*60*60, 60*60, 60, 1];
Unit:= [" wk", " d", " hr", " min", " sec"];
DoComma:= false;
for I:= 0 to 4 do
[Quot:= Sec/Amt(I);
Sec:= rem(0);
if Quot # 0 then
[if DoComma then Text(8, ", ");
DoComma:= true;
IntOut(8, Quot);
Text(8, Unit(I));
];
];
ChOut(8, $0D); ChOut(8, $8A); \terminating CR+LF
I:= 0;
loop [Str(I):= ChIn(8);
if Str(I) >= $80 then return Str;
I:= I+1;
];
];
 
[Text(0, Duration(7259));
Text(0, Duration(86400));
Text(0, Duration(6_000_000));
]</syntaxhighlight>
 
{{out}}
<pre>
2 hr, 59 sec
Line 2,274 ⟶ 4,369:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn toWDHMS(sec){ //-->(wk,d,h,m,s)
r,b:=List(),0;
foreach u in (T(60,60,24,7)){
Line 2,281 ⟶ 4,376:
}
r.append(sec).reverse()
}</langsyntaxhighlight>
Or, if you like to be concise:
<langsyntaxhighlight lang="zkl">fcn toWDHMS(sec){ //-->(wk,d,h,m,s)
T(60,60,24,7).reduce(fcn(n,u,r){ n,u=n.divr(u); r.append(u); n },
sec,r:=List()):r.append(_).reverse();
}</langsyntaxhighlight>
were the ":" op takes the left result and stuffs it into the "_" position.
<langsyntaxhighlight lang="zkl">units:=T(" wk"," d"," hr"," min"," sec");
foreach s in (T(7259,86400,6000000)){
toWDHMS(s).zip(units).pump(List,fcn([(t,u)]){ t and String(t,u) or "" })
.filter().concat(", ").println();
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,302 ⟶ 4,397:
=={{header|ZX Spectrum Basic}}==
{{trans|AWK}}
<langsyntaxhighlight lang="zxbasic">10 LET m=60: LET h=60*m: LET d=h*24: LET w=d*7
20 DATA 10,7259,86400,6000000,0,1,60,3600,604799,604800,694861
30 READ n
Line 2,323 ⟶ 4,418:
200 NEXT i
210 STOP
220 DEF FN m(a,b)=a-INT (a/b)*b</langsyntaxhighlight>
1,006

edits