Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

Convert seconds to compound duration

From Rosetta Code
Task
Convert seconds to compound duration
You are encouraged tosolve this task according to the task description, using any language you may know.
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 numberoutput string
72592 hr, 59 sec
864001 d
60000009 wk, 6 d, 10 hr, 40 min

Details

The following five units should be used:

unitsuffix used in outputconversion
weekwk1 week = 7 days
dayd1 day = 24 hours
hourhr1 hour = 60 minutes
minutemin1 minute = 60 seconds
secondsec

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., return2 min, 10 sec and not1 min, 70 sec or130 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).




11l

Translation of:Julia
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))

Action!

Library:Action! Tool Kit
Library:Action! Real Math
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)RETURNPROC 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  ODRETURNPROC Test(CHAR ARRAY s)  REAL seconds  Time t  ValR(s,seconds)  PrintR(seconds) Print(" -> ")  Convert(seconds,t)  PrintTime(t) PutE()RETURNPROC 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
Output:

Screenshot from Atari 8-bit computer

259 -> 2 hr, 59 sec86400 -> 1 d6000000 -> 9 wk, 6 d, 10 hr, 40 min

Ada

withAda.Text_IO;procedureConvertistypeTimeisrange0..10_000*356*20*60*60;-- at most 10_000 yearssubtypeValid_DurationisTimerange1..10_000*356*20*60*60;typeUnitsis(WK,D,HR,MIN,SEC);packageIOrenamesAda.Text_IO;Divide_By:constantarray(Units)ofTime:=(1_000*53,7,24,60,60);Split:array(Units)ofTime;No_Comma:Units;X:Time;Test_Cases:array(Positiverange<>)ofValid_Duration:=(6,60,3659,7_259,86_400,6_000_000,6_001_200,6_001_230,600_000_000);beginforTest_CaseofTest_CasesloopIO.Put(Time'Image(Test_Case)&" SECONDS =");X:=Test_Case;-- split X up into weeks, days, ..., secondsNo_Comma:=Units'First;forUnitinreverseUnitsloop-- Unit = SEC, ..., WK (in that order)Split(Unit):=XmodDivide_By(Unit);X:=X/Divide_By(Unit);ifUnit>No_CommaandSplit(Unit)>0thenNo_Comma:=Unit;endif;endloop;-- ouput weeks, days, ..., secondsforUnitinUnitsloop-- Unit =  WK, .., SEC (in that order)ifSplit(Unit)>0thenIO.Put(Time'Image(Split(Unit))&" "&Units'Image(Unit)&(ifNo_Comma>Unitthen","else""));endif;endloop;IO.New_Line;endloop;endConvert;
Output:
 6 SECONDS = 6 SEC 60 SECONDS = 1 MIN 3659 SECONDS = 1 HR, 59 SEC 7259 SECONDS = 2 HR, 59 SEC 86400 SECONDS = 1 D 6000000 SECONDS = 9 WK, 6 D, 10 HR, 40 MIN 6001200 SECONDS = 9 WK, 6 D, 11 HR 6001230 SECONDS = 9 WK, 6 D, 11 HR, 30 SEC 600000000 SECONDS = 992 WK, 10 HR, 40 MIN

ALGOL 68

# MODE to hold the compound duration #MODE DURATION = STRUCT( INT weeks, days, hours, minutes, seconds );# returns number of seconds converted to a DURATION #OP TODURATION = ( LONG INT number of seconds )DURATION:   BEGIN       LONG INT time     := number of 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 number of seconds converted to a DURATION #OP TODURATION = ( INT number of seconds )DURATION: TODURATION LENG number of 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 ) )
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

ALGOL W

Based on Algol 68 but Algol W does not have dynamic string handling which makes this more complex.

begin    % record structure to hold a compound duration %    record Duration ( integer weeks, days, hours, minutes, seconds );    % returns seconds converted to a Duration %    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 %    string(80) procedure durationToString ( reference(Duration) value d ) ;    begin        % appends an element of the compound duration to text %        procedure add ( integer   value componentValue                      ; 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;        logical    needSeparator;        integer    textPos;        textPos       := 0;        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.
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

APL

Works with:Dyalog APL
duration{names'wk''d''hr''min''sec'parts07246060fmt¨(parts0)/parts,¨names¯2↓∊fmt,¨', '}
Output:
      duration 72592 hr, 59 sec      duration 864001 d      duration 60000009 wk, 6 d, 10 hr, 40 min

AppleScript

Functional

-------------------- COMPOUND DURATIONS -------------------- weekParts Int -> [Int]onweekParts(intSeconds)unitParts(intSeconds,[missing value,7,24,60,60])endweekParts-- localCompoundDuration :: Int -> StringonlocalCompoundDuration(localNames,intSeconds)-- [String] -> (Int, String) -> [String]scriptformattedon|λ|(lstPair,a)setqtoitem1oflstPairifq>0then{(qasstring)&space&item2oflstPair}&aelseaendifend|λ|endscriptintercalate(", ",¬foldr(formatted,[],¬zip(weekParts(intSeconds),localNames)))endlocalCompoundDuration------------------ INTEGER DECOMPOSITION ------------------- unitParts :: Int -> [maybe Int] -> [Int]onunitParts(intTotal,unitList)-- partList :: Record -> Int -> RecordscriptpartListon|λ|(x,a)setintResttoremainingofaifxis notmissing valuethensetintModtointRestmodxsetdtoxelsesetintModtointRestsetdto1endif{remaining:(intRest-intMod)divd,parts:{intMod}&partsofa}end|λ|endscriptpartsoffoldr(partList,¬{remaining:intTotal,parts:[]},unitList)endunitParts--------------------------- TEST -------------------------onrunscriptangloNameson|λ|(n)(nasstring)&"     ->    "&¬localCompoundDuration(["wk","d","hr","min","sec"],n)end|λ|endscriptunlines(map(angloNames,[7259,86400,6000000]))endrun-------------------- GENERIC FUNCTIONS --------------------- foldr :: (a -> b -> b) -> b -> [a] -> bonfoldr(f,startValue,xs)tellmReturn(f)setvtostartValuesetlngtolengthofxsrepeatwithifromlngto1by-1setvto|λ|(itemiofxs,v,i,xs)endrepeatreturnvendtellendfoldr-- intercalate :: String -> [String] -> Stringonintercalate(delim,xs)set{dlm,mytext item delimiters}to¬{mytext item delimiters,delim}setstoxsastextsetmytext item delimiterstodlmsendintercalate-- map :: (a -> b) -> [a] -> [b]onmap(f,xs)-- The list obtained by applying f-- to each element of xs.tellmReturn(f)setlngtolengthofxssetlstto{}repeatwithifrom1tolngsetendoflstto|λ|(itemiofxs,i,xs)endrepeatreturnlstendtellendmap-- min :: Ord a => a -> a -> aonmin(x,y)ify<xthenyelsexendifendmin-- mReturn :: First-class m => (a -> b) -> m (a -> b)onmReturn(f)-- 2nd class handler function lifted into 1st class script wrapper.ifscriptisclassoffthenfelsescriptproperty|λ|:fendscriptendifendmReturn-- unlines :: [String] -> Stringonunlines(xs)-- A single string formed by the intercalation-- of a list of strings with the newline character.set{dlm,mytext item delimiters}to¬{mytext item delimiters,linefeed}setstoxsastextsetmytext item delimiterstodlmsendunlines-- zip :: [a] -> [b] -> [(a, b)]onzip(xs,ys)-- A list of step-wise pairs drawn from xs and ys-- up to the length of the shorter of those lists.setlngtomin(lengthofxs,lengthofys)setzsto{}repeatwithifrom1tolngsetendofzsto{itemiofxs,itemiofys}endrepeatreturnzsendzip
Output:
7259     ->    2 hr, 59 sec86400     ->    1 d6000000     ->    9 wk, 6 d, 10 hr, 40 min

Straightforward

onsecondsToCompoundDuration(sec)if((sec'sclassis notinteger)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)thenreturn"0 sec"-- Otherwise perform the described task.setunitsto{weeks,days,hours,minutes,1}setsuffixesto{" wk, "," d, "," hr, "," min, "," sec, "}setoutputto""repeatwithifrom1to5setunittounits'sitemisetunitValuetosecdivunitif(unitValue>0)thensetoutputtooutput&unitValue&suffixes'sitemisetsectosecmodunitif(sec=0)thenexitrepeatendrepeatreturnoutput'stext1thru-3endsecondsToCompoundDurationreturnsecondsToCompoundDuration(7259)&linefeed&¬secondsToCompoundDuration(86400)&linefeed&¬secondsToCompoundDuration(6000000)
Output:
"2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min"

Applesoft BASIC

100 DATA604800,WK,86400,D,3600,HR,60,MIN,1,SEC110 FOR I = 0 TO 4120     READ M(I), U$(I)130 NEXT140 DATA7259,86400,6000000150 ON ERR GOTO 270160     READ S170     GOSUB 200180     PRINT S " = " S$190 GOTO 160200 N = S210 S$ = ""220 FOR I = 0 TO 4230     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 I260 RETURN270 END

Arturo

Translation of:Nim
Units:[" wk"," d"," hr"," min"," sec"]Quantities:@[7*24*60*60,24*60*60,60*60,60,1]durationString:function[d][dur:didx:0result:[]while[not?zero?dur][q:dur/Quantities\[idx]ifnot?zero?q[dur:dur%Quantities\[idx]'result++~{|q||Units\[idx]|}]idx:idx+1]returnjoin.with:","result]loop[7259864006000000]'t[print[t"s =>"durationStringt]]
Output:
7259 s =>  2 hr, 59 sec 86400 s =>  1 d 6000000 s =>  9 wk, 6 d, 10 hr, 40 min

AutoHotkey

duration(n){sec:=1,min:=60*sec,hr:=60*min,day:=24*hr,wk:=7*dayw:=n//wk,n:=Mod(n,wk)d:=n//day,n:=Mod(n,day)h:=n//hr,n:=Mod(n,hr)m:=n//min,n:=Mod(n,min)s:=nreturntrim((w?w" wk, ":"")(d?d" d, ":"")(h?h" hr, ":"")(m?m" min, ":"")(s?s" sec":""),", ")}

Examples:

data=(7259864006000000)loop,parse,data,`n,`rres.=A_LoopField"`t: "duration(A_LoopField)"`n"MsgBox%resreturn

Outputs:

7259: 2 hr, 59 sec86400: 1 d6000000: 9 wk, 6 d, 10 hr, 40 min

AWK

# syntax: GAWK -f CONVERT_SECONDS_TO_COMPOUND_DURATION.AWKBEGIN{n=split("7259 86400 6000000 0 1 60 3600 604799 604800 694861",arr," ")for(i=1;i<=n;i++){printf("%9s %s\n",arr[i],howlong(arr[i]))}exit(0)}functionhowlong(seconds,n_day,n_hour,n_min,n_sec,n_week,str,x){if(seconds>=(x=60*60*24*7)){n_week=int(seconds/x)seconds=seconds%x}if(seconds>=(x=60*60*24)){n_day=int(seconds/x)seconds=seconds%x}if(seconds>=(x=60*60)){n_hour=int(seconds/x)seconds=seconds%x}if(seconds>=(x=60)){n_min=int(seconds/x)seconds=seconds%x}n_sec=int(seconds)str=(n_week>0)?(strn_week" wk, "):strstr=(n_day>0)?(strn_day" d, "):strstr=(n_hour>0)?(strn_hour" hr, "):strstr=(n_min>0)?(strn_min" min, "):strstr=(n_sec>0)?(strn_sec" sec"):strsub(/, $/,"",str)return(str)}

Output:

     7259 2 hr, 59 sec    86400 1 d  6000000 9 wk, 6 d, 10 hr, 40 min        0        1 1 sec       60 1 min     3600 1 hr   604799 6 d, 23 hr, 59 min, 59 sec   604800 1 wk   694861 1 wk, 1 d, 1 hr, 1 min, 1 sec

BASIC

Commodore BASIC

10REM CONVERT SECONDS TO COMPOUND DURATION20REM ADAPTED FROM RUN BASIC VERSION30REM ===============================================================40PRINTCHR$(14)50SEC=725960GOSUB100070SEC=8540080GOSUB100090SEC=6000000100GOSUB1000110END120REM ==============================================================1000WK=INT(SEC/60/60/24/7)1010DY=INT(SEC/60/60/24)-7*WK1020HR=INT(SEC/60/60)-24*(DY+7*WK)1030MN=INT(SEC/60)-60*(HR+24*(DY+7*WK))1040SC=SEC-60*(MN+60*(HR+24*(DY+7*WK)))1050PRINTSEC;"SEC":PRINT"  =";1055F=01060IFWK=0THEN10801070PRINTWK;"WK";:F=11080IFDY=0THEN11101090IFFTHENPRINT",";1100PRINTDY;"DY";:F=11110IFHR=0THEN11401120IFFTHENPRINT",";1130PRINTHR;"HR";:F=11140IFMN=0THEN11701150IFFTHENPRINT",";1160PRINTMN;"MIN";:F=11170IF(SC>0)ANDFTHENPRINT",";SC;"SEC":GOTO12001180IF(SC=0)ANDFTHEN12001190PRINTSC;"SEC"1200PRINT1210RETURN
Output:
7259 sec = 2 hr, 59 sec85400 sec = 23 hr, 43 min, 20 sec6000000 sec = 9 wk, 6 dy, 10 hr, 40 min

BaCon

'--- SAY_TIME Convert seconds to compound duration'--- Weeks, days hours, minutes ,secondsSUBSAY_TIME(intsec)LOCALweek,day,hour,minute,secondTYPEintweek=sec/604800day=MOD(sec/86400,7)hour=MOD(sec/3600,24)minute=MOD(sec/60,60)second=MOD(sec,60)IFweek>0THENPRINTSTR$(week)&" wk, "TOp1$SIZE100ENDIFIFday>0THENPRINTSTR$(day)&" d, "TOp2$SIZE100ENDIFIFhour>0THENPRINTSTR$(hour)&" h, "TOp3$SIZE100ENDIFIFminute>0THENPRINTSTR$(minute)&" min, "TOp4$SIZE100ENDIFIFsecond>0THENPRINTSTR$(second)&" sec "TOp5$SIZE100ENDIFPRINTp1$,p2$,p3$,p4$,p5$ENDSUB'---result   9 wk, 6 d, 10 h, 40 min, 7 secSAY_TIME(6000007)

BBC BASIC

REM >compdurationPRINTFN_convert(7259)PRINTFN_convert(86400)PRINTFN_convert(6000000)END:DEFFN_convert(seconds%)LOCALunits%(),units$(),i%,unit%,compound$DIMunits%(4)DIMunits$(4)units%()=604800,86400,3600,60,1units$()="wk","d","hr","min","sec"compound$=""FORi%=0TO4IFseconds%>=units%(i%)THENunit%=seconds%DIVunits%(i%)seconds%=seconds%MODunits%(i%)compound$+=STR$(unit%)+" "+units$(i%)IFi%<4ANDseconds%>0THENcompound$+=", "ENDIFNEXT=compound$
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

IS-BASIC

100 PROGRAM "Seconds.bas"110 NUMERIC UN(1 TO 5),SEC,UNIT120 STRING T$(1 TO 5)*3130 LET UN(1)=604800:LET UN(2)=86400:LET UN(3)=3600:LET UN(4)=60:LET UN(5)=1140 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: ":SEC160 PRINT SEC;"sec =";170 FOR I=1 TO 5180   IF SEC>=UN(I) THEN190     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

Batch File

@echo off::The Main Thing...for%%din(7259 86400 6000000)docall:duration%%dexit/b 0::/The Main Thing.::The Function...:durationsetoutput=set/a"wk=%1/604800,rem=%1%%604800"if%wk%neq 0set"output=%wk% wk,"set/a"d=%rem%/86400,rem=%rem%%%86400"if%d%neq 0set"output=%output%%d% d,"set/a"hr=%rem%/3600,rem=%rem%%%3600"if%hr%neq 0set"output=%output%%hr% hr,"set/a"min=%rem%/60,rem=%rem%%%60"if%min%neq 0set"output=%output%%min% min,"if%rem%neq 0set"output=%output%%rem% sec,"if%1gtr 0echo%1 sec =%output:~1,-1%goto:EOF::/The Function.
Output:
7259 sec = 2 hr, 59 sec86400 sec = 1 d6000000 sec = 9 wk, 6 d, 10 hr, 40 min

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
Output:
julia> beeswax("seconds to compound duration.bswx")i72592 hr, 59 secProgram finished!julia> beeswax("seconds to compound duration.bswx")i864001 dProgram finished!julia> beeswax("seconds to compound duration.bswx")i60000009 wk, 6 d, 10 hr, 40 minProgram finished!

Befunge

The value to convert is read from stdin, and the corresponding compound duration is written to stdout.

&>:"<"%\"O{rq"**+\"<"/:"<"%\"r<|":*+*5-\vv-7*"l~"/7\"d"\%7:/*83\+*:"xD"\%*83:/"<"<>\:!#v_v#-#<",",#$48*#<,#<.#<>#_:"~"%,v^_@#:$$<>.02g92p^^!:/"~"<
Output:
72592 hr, 59 sec864001 d60000009 wk, 6 d, 10 hr, 40 min

C

C: Version written in C89. Average skill level.

/* * 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(unsignedlongseconds){inti;constunsignedlongs=1;constunsignedlongm=60*s;constunsignedlongh=60*m;constunsignedlongd=24*h;constunsignedlongw=7*d;constunsignedlongcoeff[5]={w,d,h,m,s};constcharunits[5][4]={"wk","d","hr","min","sec"};staticcharbuffer[256];char*ptr=buffer;for(i=0;i<5;i++){unsignedlongvalue;value=seconds/coeff[i];seconds=seconds%coeff[i];if(value){if(ptr!=buffer)ptr+=sprintf(ptr,", ");ptr+=sprintf(ptr,"%lu %s",value,units[i]);}}returnbuffer;}/* * Main function for seconds2string program. */intmain(intargc,charargv[]){unsignedlongseconds;if((argc<2)&&scanf("%lu",&seconds)||(argc>=2)&&sscanf(argv[1],"%lu",&seconds)){printf("%s\n",seconds2string(seconds));returnEXIT_SUCCESS;}returnEXIT_FAILURE;}

C: Version written in C99. Low skill level.

#include<inttypes.h> /* requires c99 */#include<stdbool.h>  /* requires c99 */#include<stdio.h>#include<stdlib.h>#define N_EL 5uintmax_tsec_to_week(uintmax_t);uintmax_tsec_to_day(uintmax_t);uintmax_tsec_to_hour(uintmax_t);uintmax_tsec_to_min(uintmax_t);uintmax_tweek_to_sec(uintmax_t);uintmax_tday_to_sec(uintmax_t);uintmax_thour_to_sec(uintmax_t);uintmax_tmin_to_sec(uintmax_t);char*format_sec(uintmax_t);/* the primary function */intmain(intargc,char*argv[]){uintmax_tinput;char*a;if(argc<2){printf("usage: %s #seconds\n",argv[0]);return1;}input=strtoumax(argv[1],(void*)0,10/*base 10*/);if(input<1){printf("Bad input: %s\n",argv[1]);printf("usage: %s #seconds\n",argv[0]);return1;}printf("Number entered: %"PRIuMAX"\n",input);a=format_sec(input);printf(a);free(a);return0;}/* note: must free memory * after using this function */char*format_sec(uintmax_tinput){inti;boolfirst;uintmax_tweeks,days,hours,mins;/*seconds kept in input*/char*retval;FILE*stream;size_tsize;uintmax_t*traverse[N_EL]={&weeks,&days,&hours,&mins,&input};char*labels[N_EL]={"wk","d","hr","min","sec"};weeks=sec_to_week(input);input=input-week_to_sec(weeks);days=sec_to_day(input);input=input-day_to_sec(days);hours=sec_to_hour(input);input=input-hour_to_sec(hours);mins=sec_to_min(input);input=input-min_to_sec(mins);/* input now has the remaining seconds *//* open stream */stream=open_memstream(&retval,&size);if(stream==0){fprintf(stderr,"Unable to allocate memory");return0;}/* populate stream */first=true;for(i=0;i<N_EL;i++){if(*(traverse[i])!=0){if(!first){fprintf(stream,", %"PRIuMAX" %s",*(traverse[i]),labels[i]);}else{fprintf(stream,"%"PRIuMAX" %s",*(traverse[i]),labels[i]);}fflush(stream);first=false;}}fprintf(stream,"\n");fclose(stream);returnretval;}uintmax_tsec_to_week(uintmax_tseconds){returnsec_to_day(seconds)/7;}uintmax_tsec_to_day(uintmax_tseconds){returnsec_to_hour(seconds)/24;}uintmax_tsec_to_hour(uintmax_tseconds){returnsec_to_min(seconds)/60;}uintmax_tsec_to_min(uintmax_tseconds){returnseconds/60;}uintmax_tweek_to_sec(uintmax_tweeks){returnday_to_sec(weeks*7);}uintmax_tday_to_sec(uintmax_tdays){returnhour_to_sec(days*24);}uintmax_thour_to_sec(uintmax_thours){returnmin_to_sec(hours*60);}uintmax_tmin_to_sec(uintmax_tminutes){returnminutes*60;}
Output:
Number entered: 72592 hr, 59 sec Number entered: 864001 dNumber entered: 60000009 wk, 6 d, 10 hr, 40 min

C#

C#: Standard method

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;namespaceConvertSecondsToCompoundDuration{classProgram{staticvoidMain(string[]args){foreach(stringarginargs){intduration;boolisValid=int.TryParse(arg,outduration);if(!isValid){Console.Error.WriteLine("ERROR: Not an integer: {0}",arg);}if(duration<0){Console.Error.WriteLine("ERROR: duration must be non-negative",arg);}Console.WriteLine();Console.WriteLine("{0:#,##0} seconds ==> {1}",duration,FormatAsDuration(duration));}}privatestaticstringFormatAsDuration(intduration){if(duration<0)thrownewArgumentOutOfRangeException("duration");returnstring.Join(", ",GetDurationParts(duration));}privatestaticIEnumerable<string>GetDurationParts(intduration){varparts=new[]{new{Name="wk",Length=7*24*60*60*1,},new{Name="d",Length=24*60*60*1,},new{Name="h",Length=60*60*1,},new{Name="m",Length=60*1,},new{Name="s",Length=1,},};foreach(varpartinparts){intn=Math.DivRem(duration,part.Length,outduration);if(n>0)yieldreturnstring.Format("{0} {1}",n,part.Name);}}}}
Output:
7,259 seconds ==> 2 h, 59 s86,400 seconds ==> 1 d6,000,000 seconds ==> 9 wk, 6 d, 10 h, 40 m

C#: Using the TimeSpan struct and query syntax

Library:System
Library:System.Collections.Generic
Library:System.Linq
Works with:C sharp version 6
privatestaticstringConvertToCompoundDuration(intseconds){if(seconds<0)thrownewArgumentOutOfRangeException(nameof(seconds));if(seconds==0)return"0 sec";TimeSpanspan=TimeSpan.FromSeconds(seconds);int[]parts={span.Days/7,span.Days%7,span.Hours,span.Minutes,span.Seconds};string[]units={" wk"," d"," hr"," min"," sec"};returnstring.Join(", ",fromindexinEnumerable.Range(0,units.Length)whereparts[index]>0selectparts[index]+units[index]);}

C++

Works with:C++11
#include<iostream>#include<vector>usingentry=std::pair<int,constchar*>;voidprint(conststd::vector<entry>&entries,std::ostream&out=std::cout){boolfirst=true;for(constauto&e:entries){if(!first)out<<", ";first=false;out<<e.first<<" "<<e.second;}out<<'\n';}std::vector<entry>convert(intseconds){staticconstentrytime_table[]={{7*24*60*60,"wk"},{24*60*60,"d"},{60*60,"hr"},{60,"min"},{1,"sec"}};std::vector<entry>result;for(constauto&e:time_table){inttime=seconds/e.first;if(time!=0)result.emplace_back(time,e.second);seconds%=e.first;}returnresult;}intmain(){std::cout<<"   7259 sec is ";print(convert(7259));std::cout<<"  86400 sec is ";print(convert(86400));std::cout<<"6000000 sec is ";print(convert(6000000));}
Output:
   7259 sec is 2 hr, 59 sec  86400 sec is 1 d6000000 sec is 9 wk, 6 d, 10 hr, 40 min

Clojure

(require'[clojure.string:asstring])(defseconds-in-minute60)(defseconds-in-hour(*60seconds-in-minute))(defseconds-in-day(*24seconds-in-hour))(defseconds-in-week(*7seconds-in-day))(defnseconds->duration[seconds](let[weeks((juxtquotrem)secondsseconds-in-week)wk(firstweeks)days((juxtquotrem)(lastweeks)seconds-in-day)d(firstdays)hours((juxtquotrem)(lastdays)seconds-in-hour)hr(firsthours)min(quot(lasthours)seconds-in-minute)sec(rem(lasthours)seconds-in-minute)](string/join", "(filter#(not(string/blank?%))(conj[](when(>wk0)(strwk" wk"))(when(>d0)(strd" d"))(when(>hr0)(strhr" hr"))(when(> min0)(str min" min"))(when(>sec0)(strsec" sec")))))))(seconds->duration7259)(seconds->duration86400)(seconds->duration6000000)
Output:
"2 hr, 59 sec""1 d""9 wk, 6 d, 10 hr, 40 min"

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 durationstart_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))    endend start_up
Output:
7259 => 2 hr, 59 sec86400 => 1 d6000000 => 9 wk, 6 d, 10 hr, 40 min

COBOL

identificationdivision.program-id.fmt-dura.datadivision.working-storagesection.1input-secondspic 9(8).1formatted-durationpic x(30)global.1fractions.2weekspic z(3)9.2dayspic z(3)9.2hourspic z(3)9.2minutespic z(3)9.2secondspic z(3)9.1.2weeks-strpic x(4)value"wk".2days-strpic x(4)value"d".2hours-strpic x(4)value"hr".2minutes-strpic x(4)value"min".2seconds-strpic x(4)value"sec".1workbinaryglobal.2str-pospic 9(4).2chars-transferredpic 9(4).proceduredivision.begin.display"Enter duration (seconds): "noadvancingacceptinput-secondsdivideinput-secondsby60givinginput-secondsremaindersecondsdivideinput-secondsby60givinginput-secondsremainderminutesdivideinput-secondsby24givinginput-secondsremainderhoursdivideinput-secondsby7givingweeksremainderdaysmove1tostr-poscall"fmt"usingweeksweeks-strcall"fmt"usingdaysdays-strcall"fmt"usinghourshours-strcall"fmt"usingminutesminutes-strcall"fmt"usingsecondsseconds-strdisplayformatted-durationstoprun.identificationdivision.program-id.fmt.datadivision.working-storagesection.77nothingpic x.linkagesection.1formatted-valuepic x(4).1duration-sizepic x(4).proceduredivisionusingformatted-valueduration-size.begin.iffunctionnumval(formatted-value)not=0performinsert-comma-spaceunstringformatted-valuedelimitedall spaceintonothingformatted-duration(str-pos:)countchars-transferredaddchars-transferredtostr-posstringspacedelimitedsizeduration-sizedelimitedspaceintoformatted-durationpointerstr-posend-ifexitprogram.insert-comma-space.ifstr-pos>1move", "toformatted-duration(str-pos:)add2tostr-posend-if.endprogramfmt.endprogramfmt-dura.
Enter duration (seconds): 72592 hr, 59 secEnter duration (seconds): 864001 dEnter duration (seconds): 60000009 wk, 6 d, 10 hr, 40 min

Common 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*))(defunseconds->duration(seconds)(multiple-value-bind(weekswk-remainder)(floorseconds+seconds-in-week*)(multiple-value-bind(daysd-remainder)(floorwk-remainder+seconds-in-day*)(multiple-value-bind(hourshr-remainder)(floord-remainder+seconds-in-hour*)(multiple-value-bind(minutessecs)(floorhr-remainder+seconds-in-minute*)(let((chunksnil))(unless(zeropsecs)(push(formatnil"~D sec"secs)chunks))(unless(zeropminutes)(push(formatnil"~D min"minutes)chunks))(unless(zerophours)(push(formatnil"~D hr"hours)chunks))(unless(zeropdays)(push(formatnil"~D d"days)chunks))(unless(zeropweeks)(push(formatnil"~D wk"weeks)chunks))(formatt"~{~A~^, ~}~%"chunks)))))))(seconds->duration7259)(seconds->duration86400)(seconds->duration6000000)
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Crystal

Since the main function is general enough, it can be applied to other mixed bases, like the English system of measurements.

structNumberdefto_mixed_radix(*radices)result=Array(self).new(radices.size,0)n=self(0...radices.size).reverse_eachdo|i|breakifn==0divisor=radices[i]ifdivisor==0result[i]=nbreakendresult[i]=n%divisorn//=divisorendresultendenddefto_compound(num,radices,units)num.to_mixed_radix(*radices).zip(units).compact_map{|n,u|ifn!=0"#{n}#{u}"end}.join(", ")enddefsecs_to_compound(secs)to_compoundsecs,{0,7,24,60,60},["wk","d","hr","min","sec"]endputs"The task:"[7259,86400,6000000].eachdo|n|printf"%7s sec = %s\n",n,secs_to_compound(n)endputs"\n(nobody asked for this):"definches_to_compound(inches)to_compoundinches,{0,3,8,10,22,3,12},["lea","mi","fur","ch","yd","ft","in"]end[7259,86400,6000000].eachdo|n|printf"%7s in = %s\n",n,inches_to_compound(n)end
Output:
The task:   7259 sec = 2 hr, 59 sec  86400 sec = 1 d6000000 sec = 9 wk, 6 d, 10 hr, 40 min(nobody asked for this):   7259 in = 9 ch, 3 yd, 1 ft, 11 in  86400 in = 1 mi, 2 fur, 9 ch, 2 yd6000000 in = 31 lea, 1 mi, 5 fur, 5 ch, 16 yd, 2 ft

D

importstd.stdio,std.conv,std.algorithm;immutableuintSECSPERWEEK=604_800;immutableuintSECSPERDAY=86_400;immutableuintSECSPERHOUR=3_600;immutableuintSECSPERMIN=60;stringConvertSeconds(inuintseconds){uintrem=seconds;uintweeks=rem/SECSPERWEEK;rem%=SECSPERWEEK;uintdays=rem/SECSPERDAY;rem%=SECSPERDAY;uinthours=rem/SECSPERHOUR;rem%=SECSPERHOUR;uintmins=rem/SECSPERMIN;rem%=SECSPERMIN;stringformatted="";(weeks!=0)?formatted~=(weeks.to!string~" wk, "):formatted;(days!=0)?formatted~=(days.to!string~" d, "):formatted;(hours!=0)?formatted~=(hours.to!string~" hr, "):formatted;(mins!=0)?formatted~=(mins.to!string~" min, "):formatted;(rem!=0)?formatted~=(rem.to!string~" sec"):formatted;if(formatted.endsWith(", "))returnformatted[0..$-2];returnformatted;}voidmain(){7_259.ConvertSeconds.writeln;86_400.ConvertSeconds.writeln;6_000_000.ConvertSeconds.writeln;}
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Delphi

Works with:Delphi version 6.0
Library:SysUtils,StdCtrls,DateUtils


constTestData:array[0..2]ofinteger=(7259,86400,6000000);functionSecondsToFormatDate(Sec:integer):string;varDT:TDateTime;varWeeks:integer;varAYear,AMonth,ADay,AHour,AMinute,ASecond,AMilliSecond:Word;constSecPerDay=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}ifaDay<30thenaDay:=aDay+1elseaDay:=aDay-30;Result:='';ifWeeks<>0thenResult:=Result+IntToStr(Weeks)+' wk, ';ifADay<>0thenResult:=Result+IntToStr(ADay)+' d, ';ifAHour<>0thenResult:=Result+IntToStr(AHour)+' hr, ';ifAMinute<>0thenResult:=Result+IntToStr(AMinute)+' min, ';ifASecond<>0thenResult:=Result+IntToStr(ASecond)+' sec, ';end;procedureShowFormatedDataTime(Memo:TMemo);varI:integer;beginforI:=0toHigh(TestData)doMemo.Lines.Add(IntToStr(TestData[I])+' = '+SecondsToFormatDate(TestData[I]));end;
Output:
7259 = 2 hr, 59 sec, 86400 = 1 d, 6000000 = 9 wk, 6 d, 10 hr, 40 min, Elapsed Time: 2.900 ms.


DuckDB

Works with:DuckDB version V1.0
createorreplacefunctionnonzero(n,text)as(if(n>0,format('{:d} {:s}',trunc(n),text),''));createorreplacefunctionseconds_to_time(secs)as(if(secs=0,'0 sec',[(secs//60//60//24//7).nonzero('wk'),((secs//60//60//24)%7).nonzero('d'),((secs//60//60)%24).nonzero('hr'),((secs//60)%60).nonzero('min'),(trunc(secs)%60).nonzero('sec')].list_filter(x->x!='').array_to_string(', ')));selectn,seconds_to_time(n)fromunnest([0,7259,86400,6000000])_(n);
Output:
┌─────────┬──────────────────────────┐│    n    │    seconds_to_time(n)    ││  int32  │         varchar          │├─────────┼──────────────────────────┤│       0 │ 0 sec                    ││    7259 │ 2 hr, 59 sec             ││   86400 │ 1 d                      ││ 6000000 │ 9 wk, 6 d, 10 hr, 40 min │└─────────┴──────────────────────────┘

EasyLang

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 7259print split 86400print split 6000000
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Elixir

defmoduleConvertdo@minute60@hour@minute*60@day@hour*24@week@day*7@divisor[@week,@day,@hour,@minute,1]defsec_to_str(sec)do{_,[s,m,h,d,w]}=Enum.reduce(@divisor,{sec,[]},fndivisor,{n,acc}->{rem(n,divisor),[div(n,divisor)|acc]}end)["#{w} wk","#{d} d","#{h} hr","#{m} min","#{s} sec"]|>Enum.reject(fnstr->String.starts_with?(str,"0")end)|>Enum.join(", ")endendEnum.each([7259,86400,6000000],fnsec->:io.fwrite"~10w sec : ~s~n",[sec,Convert.sec_to_str(sec)]end)
Output:
      7259 sec : 2 hr, 59 sec     86400 sec : 1 d   6000000 sec : 9 wk, 6 d, 10 hr, 40 min

Erlang

Translation of:Haskell

Functionmapaccumr/3 is adapted fromhere.

Functionintercalate/2 is copied froma Tim Fletcher's GitHub repository.

-module(convert_seconds).-export([test/0]).test()->lists:map(funconvert/1,[7259,86400,6000000]),ok.convert(Seconds)->io:format("~7s seconds =~s\n",[integer_to_list(Seconds),compoundDuration(Seconds)]).% Compound duration of t seconds.  The argument is assumed to be positive.compoundDuration(Seconds)->intercalate(", ",lists:map(fun({D,L})->io_lib:format("~p~s",[D,L])end,compdurs(Seconds))).% Time broken down into non-zero durations and their labels.compdurs(T)->Ds=reduceBy(T,lists:map(fun(Dl)->element(1,Dl)end,tl(durLabs()))),lists:filter(fun(Dl)->element(1,Dl)/=0end,lists:zip(Ds,lists:map(fun(Dl)->element(2,Dl)end,durLabs()))).% Duration/label pairs.durLabs()->[{undefined,"wk"},{7,"d"},{24,"hr"},{60,"min"},{60,"sec"}].reduceBy(N,Xs)->{N_,Ys}=mapaccumr(funquotRem/2,N,Xs),[N_|Ys].quotRem(X1,X2)->{X1divX2,X1remX2}.% **************************************************% Adapted from http://lpaste.net/edit/47875% **************************************************mapaccuml(_,I,[])->{I,[]};mapaccuml(F,I,[H|T])->{Accum,NH}=F(I,H),{FAccum,NT}=mapaccuml(F,Accum,T),{FAccum,[NH|NT]}.mapaccumr(_,I,[])->{I,[]};mapaccumr(F,I,L)->{Acc,Ys}=mapaccuml(F,I,lists:reverse(L)),{Acc,lists:reverse(Ys)}.% **************************************************% **************************************************% Copied from https://github.com/tim/erlang-oauth/blob/master/src/oauth.erl% **************************************************intercalate(Sep,Xs)->lists:concat(intersperse(Sep,Xs)).intersperse(_,[])->[];intersperse(_,[X])->[X];intersperse(Sep,[X|Xs])->[X,Sep|intersperse(Sep,Xs)].% **************************************************

Output:

   7259 seconds = 2 hr, 59 sec  86400 seconds = 1 d6000000 seconds = 9 wk, 6 d, 10 hr, 40 min

F#

openSystemletconvertseconds=letspan=TimeSpan.FromSeconds(seconds|>float)let(wk,day)=Math.DivRem(span.Days,7)letparts=[(wk,"wk");(day,"day");(span.Hours,"hr");(span.Minutes,"min");(span.Seconds,"sec")]letresult=List.foldBack(fun(n,u)acc->(ifn>0thenn.ToString()+" "+uelse"")+(ifn>0&&acc.Length>0then", "else"")+acc)parts""ifresult.Length>0thenresultelse"0 sec"[<EntryPoint>]letmainargv=argv|>Seq.map(funstr->letsec=UInt32.Parsestrin(sec,convertsec))|>Seq.iter(fun(s,v)->printfn"%10i = %s"sv)0
Output:
>RosettaCode 7259 86400 6000000      7259 = 2 hr, 59 sec     86400 = 1 day   6000000 = 9 wk, 6 day, 10 hr, 40 min

Factor

USING:assocsiokernelmathmath.parserqwsequencessequences.generalizations;:mod/(xy--wz)/modswap;:convert(n--seq)60mod/60mod/24mod/7mod/5narrayreverse;:.time(n--)convert[number>string]mapqw{wkdhrminsec}zip[first"0"=]reject[" "join]map", "joinprint;7259 86400 6000000[.time]tri@
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Forth

Works with:Gforth version 0.7.3
CREATEC0,:.,C@IF.","THEN1C!;:.TIME( n --)[6060247***]L/MOD?DUP-IF.,.."wk"THEN[606024**]L/MOD?DUP-IF.,.."d"THEN[6060*]L/MOD?DUP-IF.,.."hr"THEN[60]L/MOD?DUP-IF.,.."min"THEN?DUP-IF.,.."sec"THEN0C!;
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Fortran

If the PARAMETER statements were replaced (say with suitable DATA statements) then this could be compiled with Fortran 77, if a find-last-non-blank function were to be supplied and a supplementary scratchpad used so that the numbers could be placed without leading spaces (thus "9" and "10", not " 9") because the I0 format specifier is a F90 facility. Earlier Fortran compilers lacking a CHARACTER variable would present further difficulty.

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.

SUBROUTINEPROUST(T)!Remembrance of time passed.INTEGERT!The time, in seconds. Positive only, please.INTEGERNTYPES!How many types of time?PARAMETER(NTYPES=5)!This should do.INTEGERUSIZE(NTYPES)!Size of the time unit.CHARACTER*3UNAME(NTYPES)!Name of the time unit.PARAMETER(USIZE=(/7*24*60*60,24*60*60,60*60,60,1/))!The compiler does some arithmetic.PARAMETER(UNAME=(/"wk","d","hr","min","sec"/))!Approved names, with trailing spaces.CHARACTER*28TEXT!A scratchpad.INTEGERI,L,N,S!Assistants.S=T!A copy I can mess with.L=0!No text has been generated.DOI=1,NTYPES!Step through the types to do so.N=S/USIZE(I)!Largest first.IF(N.GT.0)THEN!Above the waterline?S=S-N*USIZE(I)!Yes! Remove its contribution.IF(L.GT.0)THEN!Is this the first text to be rolled?L=L+2!No.TEXT(L-1:L)=", "!Cough forth some punctuation.END IF!Now ready for this count.WRITE(TEXT(L+1:),1)N,UNAME(I)!Place, with the unit name.1FORMAT(I0,1X,A)!I0 means I only: variable-length, no leading spaces.L=LEN_TRIM(TEXT)!Find the last non-blank resulting.END IF!Since I'm not keeping track.END DO!On to the next unit.Castforththeresult.WRITE(6,*)T,">",TEXT(1:L),"<"!With annotation.END!Simple enough with integers.PROGRAMMARCEL!Stir the cup.CALLPROUST(7259)CALLPROUST(7260)CALLPROUST(86400)CALLPROUST(6000000)CALLPROUST(0)CALLPROUST(-666)END

Output:

        7259 >2 hr, 59 sec<        7260 >2 hr, 1 min<       86400 >1 d<     6000000 >9 wk, 6 d, 10 hr, 40 min<           0 ><        -666 ><

FreeBASIC

'FreeBASIC version 1.05 32/64 bitSubShow(mAsLong)DimAsLongc(1To5)={604800,86400,3600,60,1}DimAsStringg(1To5)={" Wk"," d"," hr"," min"," sec"},commaDimAsLongb(1To5),flag,m2=mRedimAsLongs(0)FornAsLong=1To5Ifm>=c(n)ThenDoRedimPreserves(Ubound(s)+1)s(Ubound(s))=c(n)m=m-c(n)LoopUntilm<c(n)EndIfNextnFornAsLong=1ToUbound(s)FormAsLong=1To5Ifs(n)=c(m)Thenb(m)+=1NextmNextnPrintm2;" seconds = ";FornAsLong=1To5Ifb(n)Then:comma=Iif(n<5Andalsob(n+1),","," and"):flag+=1Ifflag=1Thencomma=""Printcomma;b(n);g(n);EndIfNextPrintEndSub#definesecondsShow7259secondsShow86400secondsShow6000000secondssleep

Output:

 7259 seconds =  2 hr and 59 sec 86400 seconds =  1 d 6000000 seconds =  9 Wk, 6 d, 10 hr and 40 min

Frink

Frink's-> 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.

wk := weekn = eval[input["Enter duration in seconds: "]]res = n s -> [0, "wk", "d", "hr", "min", "sec", 0]res =~ %s/, 0[^,]+//gprintln[res]

FutureBasic

Translation of:C
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  nextend fn = stringNSLog(@"%@",fn CompoundDurationString(7259))NSLog(@"%@",fn CompoundDurationString(86400))NSLog(@"%@",fn CompoundDurationString(6000000))HandleEvents
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Gambas

Click this link to run this code

PublicSubMain()DimiInputAsInteger[]=[7259,86400,6000000]'Input detailsDimiChecksAsInteger[]=[604800,86400,3600,60]'Weeks, days, hours, mins in secondsDimiTimeAsNewInteger[5]'To store wk, d, hr, min & secDimiOriginal,iSec,iLoopAsInteger'Various integersDimsOrdAsString[]=[" wk"," d"," hr"," min"," sec"]'To add to the output stringDimsOutputAsString'Output stringForEachiSecIniInput'For each iInputiOriginal=iSec'Store orginal value in secondsiTime[4]=iSec'Store seconds in iTime[4]ForiLoop=0To3'Loop through wk, d, hr, min & secIfiTime[4]>=iChecks[iLoop]Then'Check if value is = to wk, d, hr, miniTime[iLoop]=Int(iTime[4]/iChecks[iLoop])'Put the correct value for wk, d, hr, min in iTimeiTime[4]=iTime[4]-(iTime[iLoop]*iChecks[iLoop])'Remove the amount of seconds for wk, d, hr, min from iTime[4]EndifNextForiLoop=0To4'Loop through wk, d, hr, min & secsIfiTime[iLoop]>0ThensOutput&=", "&Str(iTime[iLoop])&sOrd[iLoop]'Add comma and ordinal as neededNextIfLeft(sOutput,2)=", "ThensOutput=Mid(sOutput,3)'Remove unnecessary ", "sOutput=Format(Str(iOriginal),"#######")&" Seconds = "&sOutput'Add original seconds to the output stringPrintsOutput'Print sOutput stringsOutput=""'Clear the sOutput stringiTime=NewInteger[5]'Reset iTime[]NextEnd

Output:

   7259 Seconds = 2 hr, 59 sec  86400 Seconds = 1 d6000000 Seconds = 9 wk, 6 d, 10 hr, 40 min

Go

packagemainimport"fmt"funcmain(){fmt.Println(TimeStr(7259))fmt.Println(TimeStr(86400))fmt.Println(TimeStr(6000000))}funcTimeStr(secint)(resstring){wks,sec:=sec/604800,sec%604800ds,sec:=sec/86400,sec%86400hrs,sec:=sec/3600,sec%3600mins,sec:=sec/60,sec%60CommaRequired:=falseifwks!=0{res+=fmt.Sprintf("%d wk",wks)CommaRequired=true}ifds!=0{ifCommaRequired{res+=", "}res+=fmt.Sprintf("%d d",ds)CommaRequired=true}ifhrs!=0{ifCommaRequired{res+=", "}res+=fmt.Sprintf("%d hr",hrs)CommaRequired=true}ifmins!=0{ifCommaRequired{res+=", "}res+=fmt.Sprintf("%d min",mins)CommaRequired=true}ifsec!=0{ifCommaRequired{res+=", "}res+=fmt.Sprintf("%d sec",sec)}return}
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Haskell

importControl.Monad(forM_)importData.List(intercalate,mapAccumR)importSystem.Environment(getArgs)importText.Printf(printf)importText.Read(readMaybe)reduceBy::Integrala=>a->[a]->[a]n`reduceBy`xs=n':yswhere(n',ys)=mapAccumRquotRemnxs-- Duration/label pairs.durLabs::[(Integer,String)]durLabs=[(undefined,"wk"),(7,"d"),(24,"hr"),(60,"min"),(60,"sec")]-- Time broken down into non-zero durations and their labels.compdurs::Integer->[(Integer,String)]compdurst=letds=t`reduceBy`(mapfst$taildurLabs)infilter((/=0).fst)$zipds(mapsnddurLabs)-- Compound duration of t seconds.  The argument is assumed to be positive.compoundDuration::Integer->StringcompoundDuration=intercalate", ".map(uncurry$printf"%d %s").compdursmain::IO()main=doargs<-getArgsforM_args$\arg->casereadMaybeargofJustn->printf"%7d seconds = %s\n"n(compoundDurationn)Nothing->putStrLn$"Invalid number of seconds: "++arg
Output:
   7259 seconds = 2 hr, 59 sec  86400 seconds = 1 d6000000 seconds = 9 wk, 6 d, 10 hr, 40 min


Or, parameterising both the local names for these durations, and also the working assumptions about hours per day, and days per week:

importData.List(intercalate,mapAccumR)---------------- COMPOUND DURATION STRINGS ---------------durationString::String->String->Int->Int->[String]->Int->StringdurationStringcomponentGapnumberLabelGapdaysPerWeekhoursPerDayxsn=intercalatecomponentGap(foldr(timeTagsnumberLabelGap)[](zip(weekPartsdaysPerWeekhoursPerDayn)xs))timeTags::String->(Int,String)->[String]->[String]timeTagsnumberLabelGap(n,s)xs|0<n=intercalatenumberLabelGap[shown,s]:xs|otherwise=xsweekParts::Int->Int->Int->[Int]weekPartsdaysPerWeekhoursPerDay=snd.flip(mapAccumRbyUnits)[0,daysPerWeek,hoursPerDay,60,60]byUnits::Int->Int->(Int,Int)byUnitsrestx=(quot(rest-m)u,m)where(u,m)|0<x=(x,remrestx)|otherwise=(1,rest)--------------------------- TEST -------------------------translation::String->Int->Int->Int->StringtranslationlocaldaysPerWeekhoursPerDayn=intercalate"  ->  "$[show,durationString", "" "daysPerWeekhoursPerDay(wordslocal)]<*>[n]main::IO()main=doletnames="wk d hr min sec"lettests=[7259,86400,6000000]putStrLn"Assuming 24 hrs per day:"mapM_(putStrLn.translationnames724)testsputStrLn"\nor, at 8 hours per day, 5 days per week:"mapM_(putStrLn.translationnames58)tests
Output:
Assuming 24/7:7259  ->  2 hr, 59 sec86400  ->  1 d6000000  ->  9 wk, 6 d, 10 hr, 40 minor, at 8 working hours per day, 5 days per week:7259  ->  2 hr, 59 sec86400  ->  3 d6000000  ->  41 wk, 3 d, 2 hr, 40 min

Hobbes

// @test: [compound(s) | s <- [7259, 86400, 6000000]]compound s = (s / 604800, s % 604800 / 86400, s % 86400 / 3600, s % 3600 / 60, s % 60)
Output:
0 0  2  0 590 1  0  0  09 6 10 40  0

J

Implementation:

fmtsecs=:verbdefineseq=.07246060#:y}:;:inv,(0~:seq)#(8!:0seq),.<;.2'wk,d,hr,min,sec,')

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:

fmtsecs72592hr,59secfmtsecs864001dfmtsecs60000009wk,6d,10hr,40min

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}

Java

This is a relatively simple task in Java, using the modulus-remainder operator.

Stringduration(intseconds){StringBuilderstring=newStringBuilder();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));}returnstring.toString();}
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min


An alternate demonstration

publicclassCompoundDuration{publicstaticvoidmain(String[]args){compound(7259);compound(86400);compound(6000_000);}privatestaticvoidcompound(longseconds){StringBuildersb=newStringBuilder();seconds=addUnit(sb,seconds,604800," wk, ");seconds=addUnit(sb,seconds,86400," d, ");seconds=addUnit(sb,seconds,3600," hr, ");seconds=addUnit(sb,seconds,60," min, ");addUnit(sb,seconds,1," sec, ");sb.setLength(sb.length()>2?sb.length()-2:0);System.out.println(sb);}privatestaticlongaddUnit(StringBuildersb,longsec,longunit,Strings){longn;if((n=sec/unit)>0){sb.append(n).append(s);sec%=(n*unit);}returnsec;}}
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

JavaScript

Functional

ES5

(function(){'use strict';// angloDuration :: Int -> StringfunctionangloDuration(intSeconds){returnzip(weekParts(intSeconds),['wk','d','hr','min','sec']).reduce(function(a,x){returna.concat(x[0]?([(x[0].toString()+' '+x[1])]):[]);},[]).join(', ');}// weekParts :: Int -> [Int]functionweekParts(intSeconds){return[undefined,7,24,60,60].reduceRight(function(a,x){varintRest=a.remaining,intMod=isNaN(x)?intRest:intRest%x;return{remaining:(intRest-intMod)/(x||1),parts:[intMod].concat(a.parts)};},{remaining:intSeconds,parts:[]}).parts}// GENERIC ZIP// zip :: [a] -> [b] -> [(a,b)]functionzip(xs,ys){returnxs.length===ys.length?(xs.map(function(x,i){return[x,ys[i]];})):undefined;}// TESTreturn[7259,86400,6000000].map(function(intSeconds){returnintSeconds.toString()+'    ->    '+angloDuration(intSeconds);}).join('\n');})();
Output:
7259     ->    2 hr, 59 sec86400     ->    1 d6000000     ->    9 wk, 6 d, 10 hr, 40 min


ES6

(()=>{"use strict";// ---------------- COMPOUND DURATION ----------------// compoundDuration :: [String] -> Int -> StringconstcompoundDuration=labels=>nSeconds=>weekParts(nSeconds).map((v,i)=>[v,labels[i]]).reduce((a,x)=>a.concat(x[0]?[`${x[0]}${x[1]||"?"}`]:[]),[]).join(", ");// weekParts :: Int -> [Int]constweekParts=nSeconds=>[0,7,24,60,60].reduceRight((a,x)=>{constr=a[0],mod=x!==0?r%x:r;return[(r-mod)/(x||1),[mod,...a[1]]];},[nSeconds,[]])[1];// ---------------------- TEST -----------------------// main :: IO ()constmain=()=>{constlocalNames=["wk","d","hr","min","sec"];return[7259,86400,6E6].map(nSeconds=>`${nSeconds} ->${compoundDuration(localNames)(nSeconds)}`).join("\n");};// MAIN ---returnmain();})();
Output:
7259 -> 2 hr, 59 sec86400 -> 1 d6000000 -> 9 wk, 6 d, 10 hr, 40 min

jq

Works with:jq version 1.4

Also works with gojq, the Go implementation

The program shown below will also work with jaq, the Rust implementation of jq, provided `%` is replaced everywhere by `| floor %`.The program so altered would still run using the C and Go implementations of jq.

def seconds_to_time_string:  def nonzero(text): floor | if . > 0 then "\(.) \(text)" else empty end;  if . == 0 then "0 sec"  else  [(./60/60/24/7    | nonzero("wk")),   (./60/60/24 % 7  | nonzero("d")),   (./60/60    % 24 | nonzero("hr")),   (./60       % 60 | nonzero("min")),   (.          % 60 | nonzero("sec"))]  | join(", ")  end;

Examples':

0, 7259, 86400, 6000000 | "\(.): \(seconds_to_time_string)"
Output:
$jq-r-n-fConvert_seconds_to_compound_duration.jq0:0sec7259:2hr,59sec86400:1d6000000:9wk,6d,10hr,40min

Julia

# 1.xfunctionduration(sec::Integer)::Stringt=Array{Int}([])fordmin(60,60,24,7)sec,m=divrem(sec,dm)pushfirst!(t,m)endpushfirst!(t,sec)returnjoin(["$num$unit"for(num,unit)inzip(t,["w","d","h","m","s"])ifnum>0],", ")end@showduration(7259)@showduration(86400)@showduration(6000000)
Output:
duration(7259) = "2h, 59s"duration(86400) = "1d"duration(6000000) = "9w, 6d, 10h, 40m"

K

Works with:ngn/k
F:{", "/" "/'+($x[s]),s:,&0<x}(" "\"wk d hr min sec")!07246060\

Examples:

F100"1 min, 40 sec"F7259"2 hr, 59 sec"F86400"1 d"F6000000"9 wk, 6 d, 10 hr, 40 min"

tested in ngn/k

Kotlin

funcompoundDuration(n:Int):String{if(n<0)return""// task doesn't ask for negative integers to be convertedif(n==0)return"0 sec"valweeks:Intvaldays:Intvalhours:Intvalminutes:Intvalseconds:Intvardivisor:Int=7*24*60*60varrem:Intvarresult=""weeks=n/divisorrem=n%divisordivisor/=7days=rem/divisorrem%=divisordivisor/=24hours=rem/divisorrem%=divisordivisor/=60minutes=rem/divisorseconds=rem%divisorif(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"elseresult=result.substring(0,result.length-2)returnresult}funmain(args:Array<String>){valdurations=intArrayOf(0,7,84,7259,86400,6000000)durations.forEach{println("$it\t-> ${compoundDuration(it)}")}}
Output:
0       -> 0 sec7       -> 7 sec84      -> 1 min, 24 sec7259    -> 2 hr, 59 sec86400   -> 1 d6000000 -> 9 wk, 6 d, 10 hr, 40 min

langur

val d = 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 = d(seconds)    write "{{seconds:7}} sec = "    writeln join(for[=[]] k of dur[1] {        if dur[2][k] != 0: _for ~= ["{{dur[2][k]}} {{dur[1][k]}}"]    }, by=", ")}
Output:
   7259 sec = 2 hr, 59 sec  86400 sec = 1 d6000000 sec = 9 wk, 6 d, 10 hr, 40 min

You could also convert nanoseconds to a langur duration. Langur durations use a separate count for years, months, days, hours, minutes, seconds, and nanoseconds. A "month" and a "year" are difficult to define in terms of seconds, which is one of the reasons langur has a duration type.

Liberty BASIC

I got a bit carried away and added 'years'...

[start]input "Enter SECONDS: "; secondsseconds=int(abs(seconds))if seconds=0 then print "Program complete.": endUnitsFound=0: LastFound$=""years=int(seconds/31449600): seconds=seconds mod 31449600if years then LastFound$="years"weeks=int(seconds/604800): seconds=seconds mod 604800if weeks then LastFound$="weeks"days=int(seconds/86400): seconds=seconds mod 86400if days then LastFound$="days"hours=int(seconds/3600): seconds=seconds mod 3600if hours then LastFound$="hours"minutes=int(seconds/60): seconds=seconds mod 60if minutes then LastFound$="minutes"if seconds then LastFound$="seconds"select case years    case 0    case 1: print years; " year";    case else: print years; " years";end selectselect case weeks    case 0    case 1          if years then            if LastFound$="weeks" then print " and "; else print ", ";        end if        print weeks; " week";    case else        if years then            if LastFound$="weeks" then print " and "; else print ", ";        end if        print weeks; " weeks";end selectselect case days    case 0    case 1          if years or weeks then            if LastFound$="days" then print " and "; else print ", ";        end if        print days; " day";    case else        if years or weeks then            if LastFound$="days" then print " and "; else print ", ";        end if        print days; " days";end selectselect case hours    case 0    case 1          if years or weeks or days then            if LastFound$="hours" then print " and "; else print ", ";        end if        print hours; " hour";    case else        if years or weeks or days then            if LastFound$="hours" then print " and "; else print ", ";        end if        print hours; " hours";end selectselect case minutes    case 0    case 1          if years or weeks or days or hours then            if LastFound$="minutes" then print " and "; else print ", ";        end if        print minutes; " minute";    case else        if years or weeks or days or hours then            if LastFound$="minutes" then print " and "; else print ", ";        end if        print minutes; " minutes";end selectselect case seconds    case 0    case 1          if years or weeks or days or hours or minutes then            if LastFound$="seconds" then print " and "; else print ", ";        end if        print seconds; " second";    case else        if years or weeks or days or hours or minutes then            if LastFound$="seconds" then print " and "; else print ", ";        end if        print seconds; " seconds";end selectprintgoto [start]
Output:
Enter SECONDS: 72592 hours and 59 secondsEnter SECONDS: 864001 dayEnter SECONDS: 60000009 weeks, 6 days, 10 hours and 40 minutesEnter SECONDS: 98765432131 years, 21 weeks, 4 hours, 25 minutes and 21 secondsEnter SECONDS:Program complete.

Lua

functionduration(secs)localunits,dur={"wk","d","hr","min"},""fori,vinipairs({604800,86400,3600,60})doifsecs>=vthendur=dur..math.floor(secs/v).." "..units[i]..", "secs=secs%vendendifsecs==0thenreturndur:sub(1,-3)elsereturndur..secs.." sec"endendprint(duration(7259))print(duration(86400))print(duration(6000000))

Maple

tim:=proc(s)localweeks,days,hours,minutes,seconds;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)))endproc;

Mathematica /Wolfram Language

compoundDuration[x_Integer]:=StringJoin@@(Riffle[ToString/@((({Floor[x/604800],Mod[x,604800]}/.{a_,b_}->{a,Floor[b/86400],Mod[b,86400]})/.{a__,b_}->{a,Floor[b/3600],Mod[b,3600]})/.{a__,b_}->{a,Floor[b/60],Mod[b,60]}),{" wk, "," d, "," hr, "," min, "," sec"}]//.{a___,"0",b_,c___}->{a,c})Grid[Table[{n,"secs =",compoundDuration[n]},{n,{7259,86400,6000000}}],Alignment->{Left,Baseline}]
Output:
7259secs =2 hr, 59 sec86400secs =1 d, 6000000secs =9 wk, 6 d, 10 hr, 40 min,

Nim

fromstrutilsimportaddSepconstUnits=[" 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)varduration=secvaridx=0whileduration!=0:letq=durationdivQuantities[idx]ifq!=0:duration=durationmodQuantities[idx]result.addSep(", ",0)result.add($q&Units[idx])incidx#———————————————————————————————————————————————————————————————————————————————————————————————————whenisMainModule:forsecin[7259,86400,6000000]:echosec,"s = ",$$sec
Output:
7259s = 2 hr, 59 sec86400s = 1 d6000000s = 9 wk, 6 d, 10 hr, 40 min

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).

importtimesfromalgorithmimportreversedfromstrutilsimportaddSepconstUnits=[" 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)varduration=initDuration(seconds=sec)letparts=reversed(duration.toParts[Seconds..Weeks])foridx,partinparts:ifpart!=0:result.addSep(", ",0)result.add($part&Units[idx])#———————————————————————————————————————————————————————————————————————————————————————————————————whenisMainModule:forsecin[7259,86400,6000000]:echosec,"s = ",$$sec
Output:

Output is the same.

OCaml

Works with:OCaml version 4.03+
letdivisors=[(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")] *)letcompute_durationsecs=letrecdoloopremainres=function|[]->res|(n,s)::ds->doloop(remain/n)((remainmodn,s)::res)dsindoloopsecs[](List.revdivisors)(* 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" *)letpretty_printdur=List.filter(fun(d,_)->d<>0)dur|>List.map(fun(d,l)->Printf.sprintf"%d %s"dl)|>String.concat", "(* Transform a number of seconds into the corresponding compound duration * string. * Not sure what to do with 0... *)letcompound=function|nwhenn>0->compute_durationn|>pretty_print|nwhenn=0->string_of_int0^"..."|_->invalid_arg"Number of seconds must be positive"(* Some testing... *)let()=lettest_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")]inlettestit(n,s)=letcalc=compoundninPrintf.printf"[%s] %d seconds -> %s; expected: %s\n"(ifcalc=sthen"PASS"else"FAIL")ncalcsinList.itertestittest_cases
Output:
[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

PARI/GP

Note: my own string function ssubstr() was used. You can find it here on RosettaCode Wiki.

Works with:PARI/GP version 2.7.4 and above
\\ Convert seconds to compound duration\\ 4/11/16 aevsecs2compdur(secs)={my(us=[604800,86400,3600,60,1],ut=[" wk, "," d, "," hr, "," min, "," sec"],   cd=[0,0,0,0,0],u,cdt="");for(i=1,5, u=secs\us[i]; if(u==0, next, cd[i]=u; secs-=us[i]*cd[i]));for(i=1,5, if(cd[i]==0, next, cdt=Str(cdt,cd[i],ut[i])));if(ssubstr(cdt,#cdt-1,1)==",", cdt=ssubstr(cdt,1,#cdt-2));return(cdt);}{\\ Required tests:print(secs2compdur(7259));print(secs2compdur(86400));print(secs2compdur(6000000));}
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Pascal

Works with:Extended Pascal
programconvertSecondsToCompoundDuration(output);constsuffixUnitWeek='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;typewholeNumber=0..maxInt;naturalNumber=1..maxInt;canonicalTimeSpan=recordweeks: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}functiongetCanonicalTimeSpan(duration:wholeNumber):canonicalTimeSpan;{ Perform `div`ision and update `duration`. }functionsplit(protectedunit:naturalNumber):wholeNumber;beginsplit:=durationdivunit;duration:=durationmodunitend;varresult:canonicalTimeSpan;beginwithresultdobeginweeks:=split(week);days:=split(day);hours:=split(hour);minutes:=split(minute);seconds:=durationend;{ In Pascal there needs to be _exactly_ one assignment to the }{ result variable bearing the same name as of the `function`. }getCanonicalTimeSpan:=resultend;{\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}functiontimeSpanString(protectedn:naturalNumber):stringFitForTimeSpan;constqs=quantitySeparator;varresult:stringFitForTimeSpan;beginwithgetCanonicalTimeSpan(n)dobegin{ `: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));ifdays>0thenbeginwriteStr(result,result,qs:ord(length(result)>0)*length(qs),days:1,suffixSeparator,suffixUnitDay);end;ifhours>0thenbeginwriteStr(result,result,qs:ord(length(result)>0)*length(qs),hours:1,suffixSeparator,suffixUnitHour);end;ifminutes>0thenbeginwriteStr(result,result,qs:ord(length(result)>0)*length(qs),minutes:1,suffixSeparator,suffixUnitMinute);end;ifseconds>0thenbeginwriteStr(result,result,qs:ord(length(result)>0)*length(qs),seconds:1,suffixSeparator,suffixUnitSecond);endend;timeSpanString:=resultend;{ === MAIN ============================================================= }beginwriteLn(7259,' seconds are “',timeSpanString(7259),'”');writeLn(86400,' seconds are “',timeSpanString(86400),'”');writeLn(6000000,' seconds are “',timeSpanString(6000000),'”')end.
Output:
       7259 seconds are “2 hr, 59 sec”      86400 seconds are “1 d”    6000000 seconds are “9 wk, 6 d, 10 hr, 40 min”

Perl

Direct calculation

usestrict;usewarnings;subcompound_duration{my$sec=shift;nowarnings'numeric';returnjoin', ',grep{$_>0}int($sec/60/60/24/7)." wk",int($sec/60/60/24)%7." d",int($sec/60/60)%24." hr",int($sec/60)%60." min",int($sec)%60." sec";}for(7259,86400,6000000){printf"%7d sec  =  %s\n",$_,compound_duration($_)}
Output:
   7259 sec  =  2 hr, 59 sec  86400 sec  =  1 d6000000 sec  =  9 wk, 6 d, 10 hr, 40 min

Using polymod

More general approach for mixed-radix conversions.

usestrict;usewarnings;useMath::AnyNum'polymod';subcompound_duration{my$seconds=shift;my@terms;my@durations=reversepolymod($seconds,60,60,24,7);my@timespans=<wkdhrminsec>;while(my$d=shift@durations,my$t=shift@timespans){push@terms,"$d $t"if$d}join', ',@terms}for(<72598640060000003380521>){printf"%7d sec  =  %s\n",$_,compound_duration($_)}
Output:
   7259 sec  =  2 hr, 59 sec  86400 sec  =  1 d6000000 sec  =  9 wk, 6 d, 10 hr, 40 min3380521 sec  =  5 wk, 4 d, 3 hr, 2 min, 1 sec

Phix

There is a standard function for this, for more details see builtins/pelapsed.e (which will be kept up to date, unlike having a copy here)

withjavascript_semantics?elapsed(7259)?elapsed(86400)?elapsed(6000000)
Output:
"2 hours and 59s""1 day""9 weeks, 6 days, 10 hours, 40 minutes"

You may also be interested in the timedelta() function, which converts durations to seconds, eg:

withjavascript_semanticsincludetimedate.e?elapsed(6000000-timedelta(days:=6,hours:=10))
Output:
"9 weeks, 40 minutes"

PicoLisp

(for Sec (7259 86400 6000000)   (tab (-10 -30)      Sec      (glue ", "         (extract            '((N Str)               (when (gt0 (/ Sec N))                  (setq Sec (% Sec N))                  (pack @ " " Str) ) )            (604800 86400 3600 60 1)            '("wk" "d" "hr" "min" "sec") ) ) ) )

Output:

7259      2 hr, 59 sec86400     1 d6000000   9 wk, 6 d, 10 hr, 40 min

PL/I

/* Convert seconds to Compound Duration (weeks, days, hours, minutes, seconds). */cvt: procedure options (main);/* 5 August 2015 */   declare interval float (15);   declare (unit, i, q controlled) fixed binary;   declare done bit (1) static initial ('0'b);   declare name (5) character (4) varying static initial (' wk', ' d', ' hr', ' min', ' sec' );   get (interval);   put edit (interval, ' seconds = ') (f(10), a);   if interval = 0 then do; put skip list ('0 sec'); stop; end;   do unit = 60, 60, 24, 7;      allocate q;      q = mod(interval, unit);      interval = interval / unit;   end;   allocate q; q = interval;   do i = 1 to 5;      if q > 0 then         do;            if done then put edit (', ') (a);            put edit (trim(q), name(i)) (a, a); done = '1'b;         end;      if i < 5 then free q;   end;end cvt;

Results:

        65 seconds = 1 min, 5 sec      3750 seconds = 1 hr, 2 min, 30 sec   1483506 seconds = 2 wk, 3 d, 4 hr, 5 min, 6 sec        60 seconds = 1 min      3604 seconds = 1 hr, 4 sec 100000000 seconds = 165 wk, 2 d, 9 hr, 46 min, 40 sec 987654321 seconds = 1633 wk, 4 hr, 25 min, 21 sec     86400 seconds = 1 d     86403 seconds = 1 d, 3 sec3 more to come.

Pluto

Translation of:Wren
localfunctionduration(s)ifs<1thenreturn"0 sec"endlocaldur=""localdivs={7,24,60,60,1}localunits={"wk","d","hr","min","sec"}localt=divs:reduce(|prod,div|->prod*div,1)fori=1,#divsdolocalu=s//tifu>0thendur..=$"{u} {units[i]}, "s%=tendt//=divs[i]endifdur:endswith(", ")thendur=dur:sub(1,-3)endreturndurendfor{7259,86400,6000000}assdoprint(duration(s))end
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

PowerShell

functionGet-Time{<#.SYNOPSIS        Gets a time string in the form: # wk, # d, # hr, # min, # sec.DESCRIPTION        Gets a time string in the form: # wk, # d, # hr, # min, # sec        (Values of 0 are not displayed in the string.)        Days, Hours, Minutes or Seconds in any combination may be used        as well as Start and End dates.        When used with the -AsObject switch an object containing properties        similar to a System.TimeSpan object is returned..INPUTS        DateTime or Int32.OUTPUTS        String or PSCustomObject.EXAMPLE        Get-Time -Seconds 7259.EXAMPLE        Get-Time -Days 31 -Hours 4 -Minutes 8 -Seconds 16.EXAMPLE        Get-Time -Days 31 -Hours 4 -Minutes 8 -Seconds 16 -AsObject.EXAMPLE        Get-Time -Start 3/10/2016 -End 1/20/2017.EXAMPLE        Get-Time -Start (Get-Date) -End (Get-Date).AddSeconds(6000000)  #>[CmdletBinding(DefaultParameterSetName='Date')]Param(# Start date[Parameter(Mandatory=$false,ParameterSetName='Date',Position=0)][datetime]$Start=(Get-Date),# End date[Parameter(Mandatory=$false,ParameterSetName='Date',Position=1)][datetime]$End=(Get-Date),# Days in the time span[Parameter(Mandatory=$false,ParameterSetName='Time')][int]$Days=0,# Hours in the time span[Parameter(Mandatory=$false,ParameterSetName='Time')][int]$Hours=0,# Minutes in the time span[Parameter(Mandatory=$false,ParameterSetName='Time')][int]$Minutes=0,# Seconds in the time span[Parameter(Mandatory=$false,ParameterSetName='Time')][int]$Seconds=0,[switch]$AsObject)Begin{[PSCustomObject]$timeObject="PSCustomObject"|Select-Object-PropertyWeeks,RemainingDays,Days,Hours,Minutes,Seconds,Milliseconds,Ticks,TotalDays,TotalHours,TotalMinutes,TotalSeconds,TotalMilliseconds[int]$remainingDays=0[int]$weeks=0[string[]]$timeString=@()}Process{switch($PSCmdlet.ParameterSetName){'Date'{$timeSpan=New-TimeSpan-Start$Start-End$End}'Time'{$timeSpan=New-TimeSpan-Days$Days-Hours$Hours-Minutes$Minutes-Seconds$Seconds}}$weeks=[System.Math]::DivRem($timeSpan.Days,7,[ref]$remainingDays)$timeObject.Weeks=$weeks$timeObject.RemainingDays=$remainingDays$timeObject.Days=$timeSpan.Days$timeObject.Hours=$timeSpan.Hours$timeObject.Minutes=$timeSpan.Minutes$timeObject.Seconds=$timeSpan.Seconds$timeObject.Milliseconds=$timeSpan.Milliseconds$timeObject.Ticks=$timeSpan.Ticks$timeObject.TotalDays=$timeSpan.TotalDays$timeObject.TotalHours=$timeSpan.TotalHours$timeObject.TotalMinutes=$timeSpan.TotalMinutes$timeObject.TotalSeconds=$timeSpan.TotalSeconds$timeObject.TotalMilliseconds=$timeSpan.TotalMilliseconds}End{if($AsObject){return$timeObject}if($timeObject.Weeks){$timeString+="$($timeObject.Weeks) wk"}if($timeObject.RemainingDays){$timeString+="$($timeObject.RemainingDays) d"}if($timeObject.Hours){$timeString+="$($timeObject.Hours) hr"}if($timeObject.Minutes){$timeString+="$($timeObject.Minutes) min"}if($timeObject.Seconds){$timeString+="$($timeObject.Seconds) sec"}return($timeString-join", ")}}
Output:
PS C:\Scripts> 7259, 86400, 6000000 | ForEach-Object { Get-Time -Seconds $_ }2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 minPS C:\Scripts> Get-Time -Start 3/10/2016 -End 1/20/201745 wk, 1 dPS C:\Scripts> Get-Time -Seconds 6000000 -AsObjectWeeks             : 9RemainingDays     : 6Days              : 69Hours             : 10Minutes           : 40Seconds           : 0Milliseconds      : 0Ticks             : 60000000000000TotalDays         : 69.4444444444444TotalHours        : 1666.66666666667TotalMinutes      : 100000TotalSeconds      : 6000000TotalMilliseconds : 6000000000

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.

:-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#=NmodDiv,times(T,Rem,Rest).% specifify the different time split typestime_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).
Output:
?- maplist(compound_time, [7259,86400,6000000]), !.7259: 2 hr, 59 sec86400: 1 d6000000: 9 wk, 6 d, 10 hr, 40 mintrue.?- times(N, [[wk, 9],[d, 6],[hr,10],[min,40]]), !.N = 6000000.

PureBasic

EnableExplicitProcedure.sConvertSeconds(NbSeconds)Protectedweeks,days,hours,minutes,secondsProtecteddivisor,remainderProtectedduration$=""divisor=7*24*60*60;secondsinaweekweeks=NbSeconds/divisorremainder=NbSeconds%divisordivisor/7;secondsinadaydays=remainder/divisorremainder%divisordivisor/24;secondsinanhourhours=remainder/divisorremainder%divisordivisor/60;secondsinaminuteminutes=remainder/divisorseconds=remainder%divisorIfweeks>0duration$+Str(weeks)+" wk, "EndIfIfdays>0duration$+Str(days)+" d, "EndIfIfhours>0duration$+Str(hours)+" hr, "EndIfIfminutes>0duration$+Str(minutes)+" min, "EndIfIfseconds>0duration$+Str(seconds)+" sec"EndIfIfRight(duration$,2)=", "duration$=Mid(duration$,0,Len(duration$)-2)EndIfProcedureReturnduration$EndProcedureIfOpenConsole()PrintN(ConvertSeconds(7259))PrintN(ConvertSeconds(86400))PrintN(ConvertSeconds(6000000))PrintN("")PrintN("Press any key to close the console")Repeat:Delay(10):UntilInkey()<>""CloseConsole()EndIf
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Python

Python: Procedural

>>>defduration(seconds):t=[]fordmin(60,60,24,7):seconds,m=divmod(seconds,dm)t.append(m)t.append(seconds)return', '.join('%d%s'%(num,unit)fornum,unitinzip(t[::-1],'wk d hr min sec'.split())ifnum)>>>forsecondsin[7259,86400,6000000]:print("%7d sec =%s"%(seconds,duration(seconds)))7259sec=2hr,59sec86400sec=1d6000000sec=9wk,6d,10hr,40min>>>

Python: Functional

>>>defduration(seconds,_maxweeks=99999999999):return', '.join('%d%s'%(num,unit)fornum,unitinzip([(seconds//d)%mford,min((604800,_maxweeks),(86400,7),(3600,24),(60,60),(1,60))],['wk','d','hr','min','sec'])ifnum)>>>forsecondsin[7259,86400,6000000]:print("%7d sec =%s"%(seconds,duration(seconds)))7259sec=2hr,59sec86400sec=1d6000000sec=9wk,6d,10hr,40min>>>

Or, composing a solution from pure curried functions, including themapAccumR abstraction (a combination of ofmap andreduce, 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):

'''Compound duration'''fromfunctoolsimportreducefromitertoolsimportchain# compoundDurationFromUnits :: [Num] -> [String] -> Num -> [(Num, String)]defcompoundDurationFromUnits(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.    '''returnlambdaks:lambdan:list(chain.from_iterable(map(lambdav,k:[(v,k)]if0<velse[],mapAccumR(lambdaa,x:divmod(a,x)if0<xelse(1,a))(n)(qs)[1],ks)))# --------------------------TEST---------------------------# main :: IO ()defmain():'''Tests of various durations, with a       particular set of units and labels.    '''print(fTable('Compound durations from numbers of seconds:\n')(str)(quoted("'"))(lambdan:', '.join([str(v)+' '+kforv,kincompoundDurationFromUnits([0,7,24,60,60])(['wk','d','hr','min','sec'])(n)]))([7259,86400,6000000]))# -------------------------GENERIC-------------------------# fTable :: String -> (a -> String) -># (b -> String) -> (a -> b) -> [a] -> StringdeffTable(s):'''Heading -> x display function -> fx display function ->       f -> xs -> tabular string.    '''defgo(xShow,fxShow,f,xs):ys=[xShow(x)forxinxs]w=max(map(len,ys))returns+'\n'+'\n'.join(map(lambdax,y:y.rjust(w,' ')+' -> '+fxShow(f(x)),xs,ys))returnlambdaxShow:lambdafxShow:lambdaf:lambdaxs:go(xShow,fxShow,f,xs)# mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])defmapAccumR(f):'''A tuple of an accumulation and a list derived by a combined       map and fold, with accumulation from right to left.    '''defgo(a,x):acc,y=f(a[0],x)return(acc,[y]+a[1])returnlambdaacc:lambdaxs:(reduce(go,reversed(xs),(acc,[])))# quoted :: Char -> String -> Stringdefquoted(c):'''A string flanked on both sides       by a specified quote character.    '''returnlambdas:c+s+c# MAIN ---if__name__=='__main__':main()
Output:
Compound durations from numbers of seconds:   7259 -> '2 hr, 59 sec'  86400 -> '1 d'6000000 -> '9 wk, 6 d, 10 hr, 40 min'

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 ]
Output:
7259 seconds is 2 hr, 59 sec.86400 seconds is 1 d.6000000 seconds is 9 wk, 6 d, 10 hr, 40 min.

R

duration<-function(t){max_units<-c("sec"=60,"min"=60,"hr"=24,"d"=7)times<-numeric(4)for(iin1:4){times[i]<-t%%max_units[i]t<-t%/%max_units[i]}times<-c(times,t)names(times)<-c(names(max_units),"wk")times<-rev(Filter(`+`,times))cat(paste(times,names(times)),sep=", ")cat("\n")}lapply(c(7259,86400,6000000),duration)|>invisible()
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Racket

#langracket/base(requireracket/stringracket/list)(define(seconds->compound-durationss)(define-values(wd.h.m.s)(for/fold((prev-qs)(rs(list)))((Q(in-list(list6060247))))(define-values(qr)(quotient/remainderprev-qQ))(valuesq(consrrs))))(conswd.h.m.s))(define(maybe-suffixvn)(and(positive?v)(format"~a ~a"vn)))(define(seconds->compound-duration-strings)(string-join(filter-mapmaybe-suffix(seconds->compound-durationss)'("wk""d""hr""min""sec"))", "))(module+test(requirerackunit)(check-equal?(seconds->compound-durations7259)(list002059))(check-equal?(seconds->compound-durations86400)(list01000))(check-equal?(seconds->compound-durations6000000)(list9610400))(check-equal?(seconds->compound-duration-string7259)"2 hr, 59 sec")(check-equal?(seconds->compound-duration-string86400)"1 d")(check-equal?(seconds->compound-duration-string6000000)"9 wk, 6 d, 10 hr, 40 min"));; Tim Brown 2015-07-21
Output:

All tests pass... there is no output.

Raku

(formerly Perl 6)

The built-inpolymod method (which is a generalization of thedivmod function known from other languages), is a perfect match for a task like this:

subcompound-duration ($seconds) {    ($seconds.polymod(60,60,24,7)Z<sec min hr d wk>)    .grep(*[0]).reverse.join(", ")}# Demonstration:for7259,86400,6000000 {say"{.fmt: '%7d'} sec  =  {compound-duration $_}";}
Output:
   7259 sec  =  2 hr, 59 sec  86400 sec  =  1 d6000000 sec  =  9 wk, 6 d, 10 hr, 40 min

REXX

version 1

/* REXX ---------------------------------------------------------------* Format seconds into a time string*--------------------------------------------------------------------*/Calltest7259,'2 hr, 59 sec'Calltest86400,'1 d'Calltest6000000,'9 wk, 6 d, 10 hr, 40 min'Calltest123.50,'2 min, 3.5 sec'Calltest123.00,'2 min, 3 sec'Calltest0.00,'0 sec'Exittest:Parseargsecs,xresres=sec2ct(secs)SayresIfres<>xresThenSay'**ERROR**'Returnsec2ct:ParseArgs/*m=s%60; s=s//60h=m%60; m=m//60d=h%24; h=h//24w=d%7;  d=d//7*/Ifs=0ThenReturn'0 sec'ParseValuesplit(s,60)withmsParseValuesplit(m,60)withhmParseValuesplit(h,24)withdhParseValuesplit(d,7)withwdol=''Ifw>0Thenol=olw'wk,'Ifd>0Thenol=old'd,'Ifh>0Thenol=olh'hr,'Ifm>0Thenol=olm'min,'Ifs>0Thenol=ol(s/1)'sec'ol=strip(ol)ol=strip(ol,,',')Returnolsplit:ProcedureParseArgwhat,howa=what%howb=what//howReturnab
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min2 min, 3.5 sec2 min, 3 sec0 sec

version 2

This REXX version can also handle fractional (seconds) as well as values of zero (time units).

/*rexx program  demonstrates  how to convert a number of seconds  to  bigger time units.*/parsearg@;if@=''then@=7259864006000000/*Not specified?  Then use the default.*/doj=1forwords(@);z=word(@,j)/* [↓]  process each number in the list*/sayright(z,25)'seconds:  'convSec(z)/*convert a number to bigger time units*/end/*j*/exit/*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/convSec:parseargx/*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     "  "    */ifx\==0thens=word(s0,1)+x'sec'/*handle fractional (residual) seconds.*/$=strip(space(wdhms),,",");if$==''thenz=0"sec"/*handle 0 sec.*/return$/*──────────────────────────────────────────────────────────────────────────────────────*/timeU:parseargu,$;_=x%u;if_==0thenreturn'';x=x-_*u;return_$","
output  when using the default (internal) inputs:
                     7259 seconds:   2 hr, 59 sec                    86400 seconds:   1 d                  6000000 seconds:   9 wk, 6 d, 10 hr, 40 min
output  when using the inputs:       1800.7   123.50   123.00   0.00
                   1800.7 seconds:   30 min, 0.7 sec                   123.50 seconds:   2 min, 3.50 sec                   123.00 seconds:   2 min, 3 sec                     0.00 seconds:   0 sec

Ring

sec = 6000005week = floor(sec/60/60/24/7)if week > 0 see sec    see " seconds is " + week + " weeks " okday = floor(sec/60/60/24) % 7if day > 0 see day   see " days " ok hour = floor(sec/60/60) % 24if hour > 0 see hour   see " hours " ok minute = floor(sec/60) % 60if minute > 0 see minute   see " minutes " oksecond = sec % 60if second > 0 see second   see " seconds" + nl ok

RPL

≪ MOD LAST / FLOOR ≫ 'DIVMOD' STO≪ {" wk" " d" " hr" " min" " sec" } → unit   ≪ 60DIVMOD 60DIVMOD 24DIVMOD 7DIVMOD      1 SF ""       1 unit SIZEFOR jIF SWAPTHEN            LAST →STR unit j GET +IF 1 FC?CTHEN ", " SWAP +END            +ENDNEXT≫ ≫ '→CDUR' STO

Users of HP-48G and newer models can replace the60DIVMOD 60DIVMOD 24DIVMOD 7DIVMOD line by:

{ 60 60 24 7 } 1 ≪ MOD LAST / FLOOR ≫ DOSUBS OBJ→ DROP
7259→CDUR86400→CDUR6000000→CDUR10!→CDUR
Output:
4: "2 hr, 59 sec"3: "1 d"2: "9 wk, 6 d, 10 hr, 40 min"1: "6 wk"

Ruby

MINUTE=60HOUR=MINUTE*60DAY=HOUR*24WEEK=DAY*7defsec_to_str(sec)w,rem=sec.divmod(WEEK)d,rem=rem.divmod(DAY)h,rem=rem.divmod(HOUR)m,s=rem.divmod(MINUTE)units=["#{w} wk","#{d} d","#{h} h","#{m} min","#{s} sec"]units.reject{|str|str.start_with?("0")}.join(", ")end[7259,86400,6000000].each{|t|puts"#{t}\t:#{sec_to_str(t)}"}

Output:

7259: 2 h, 59 sec86400: 1 d6000000: 9 wk, 6 d, 10 h, 40 min

Run BASIC

sec = 6000005week= int(sec/60/60/24/7)day= int(sec/60/60/24) mod 7hour= int(sec/60/60) mod 24minute= int(sec/60) mod 60second= sec mod 60print sec;" seconds is "; if week > 0 then print week;" weeks ";if day > 0 then print day;" days "; if hour > 0 then print hour;" hours ";if minute > 0 then print minute;" minutes ";if second > 0 then print second;" seconds"

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.

usestd::fmt;structCompoundTime{w:usize,d:usize,h:usize,m:usize,s:usize,}macro_rules!reduce{($s:ident,$(($from:ident,$to:ident,$factor:expr)),+)=>{{$($s.$to+=$s.$from/$factor;$s.$from%=$factor;)+}}}implCompoundTime{#[inline]fnnew(w:usize,d:usize,h:usize,m:usize,s:usize)->Self{CompoundTime{w:w,d:d,h:h,m:m,s:s,}}#[inline]fnbalance(&mutself){reduce!(self,(s,m,60),(m,h,60),(h,d,24),(d,w,7));}}implfmt::DisplayforCompoundTime{fnfmt(&self,f:&mutfmt::Formatter)->fmt::Result{write!(f,"{}w {}d {}h {}m {}s",self.w,self.d,self.h,self.m,self.s)}}fnmain(){letmutct=CompoundTime::new(0,3,182,345,2412);println!("Before: {}",ct);ct.balance();println!("After: {}",ct);}

Scala

//Converting Seconds to Compound Durationobjectseconds{defmain(args:Array[String]){println("Enter the no.")valinput=scala.io.StdIn.readInt()varweek_r:Int=input%604800varweek:Int=(input-week_r)/604800varday_r:Int=week_r%86400varday:Int=(week_r-day_r)/86400varhour_r:Int=day_r%3600varhour:Int=(day_r-hour_r)/3600varminute_r:Int=hour_r%60varminute:Int=(hour_r-minute_r)/60varsec:Int=minute_r%60println("Week = "+week)println("Day = "+day)println("Hour = "+hour)println("Minute = "+minute)println("Second = "+sec)}}

Scheme

Library:Scheme/SRFIs

This version uses delete from SRFI 1 and string-join from SRFI 13:

(import(schemebase)(schemewrite)(srfi1)(only(srfi13)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->durationseconds)(define(formatvalunit)(if(zero?val)""(string-append(number->stringval)" "unit)))(let*-values(((weekswk-remainder)(floor/seconds*seconds-in-week*))((daysdy-remainder)(floor/wk-remainder*seconds-in-day*))((hourshr-remainder)(floor/dy-remainder*seconds-in-hour*))((minutesmn-remainder)(floor/hr-remainder*seconds-in-minute*)))(string-join(delete""(list(formatweeks"wk")(formatdays"d")(formathours"hr")(formatminutes"min")(formatmn-remainder"sec"))string=?)", ")))(display(seconds->duration7259))(newline)(display(seconds->duration86400))(newline)(display(seconds->duration6000000))(newline)
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Sidef

Translation of:Raku
funcpolymod(n,*divs){gather{divs.each{|i|varm=take(n%i)(n-=m)/=i}take(n)}}funccompound_duration(seconds){(polymod(seconds,60,60,24,7)~Z<secminhrdwk>).grep{|a|a[0]>0}.reverse.map{.join(' ')}.join(', ')}[7259,86400,6000000].each{|s|say"#{'%7d'%s} sec  =#{compound_duration(s)}"}
Output:
   7259 sec  =  2 hr, 59 sec  86400 sec  =  1 d6000000 sec  =  9 wk, 6 d, 10 hr, 40 min

Standard ML

localfunfmtNonZero(0,_,list)=list|fmtNonZero(n,s,list)=Int.toStringn^" "^s::listfundivModHead(_,[])=[]|divModHead(d,head::tail)=headdivd::headmodd::tailinfuncompoundDurationseconds=letvaldigits=foldldivModHead[seconds][60,60,24,7]andunits=["wk","d","hr","min","sec"]inString.concatWith", "(ListPair.foldrfmtNonZero[](digits,units))endendval()=app(fns=>print(compoundDurations^"\n"))[7259,86400,6000000]

Swift

funcduration(_secs:Int)->String{ifsecs<=0{return""}letunits=[(604800,"wk"),(86400,"d"),(3600,"hr"),(60,"min")]varsecs=secsvarresult=""for(period,unit)inunits{ifsecs>=period{result+="\(secs/period)\(unit), "secs=secs%period}}ifsecs==0{result.removeLast(2)// remove ", "}else{result+="\(secs) sec"}returnresult}print(duration(7259))print(duration(86400))print(duration(6000000))

Tcl

The data-driven procedure below can be customised to use different breakpoints, simply by editing the dictionary.

procsec2str{i}{setfactors{sec60min60hr24d7wkInf}setresult""foreach{labelmax}$factors{if{$i>=$max}{setr[expr{$i%$max}]seti[expr{$i/$max}]if{$r}{lappendresult"$r $label"}}else{if{$i>0}{lappendresult"$i $label"}break}}join[lreverse$result]", "}proccheck{cmdres}{setr[uplevel1$cmd]if{$req$res}{puts"Ok! $cmd \t = $res"}else{puts"ERROR: $cmd = $r \t expected $res"}}check{sec2str7259}{2hr,59sec}check{sec2str86400}{1d}check{sec2str6000000}{9wk,6d,10hr,40min}
Output:
Ok! sec2str 7259         = 2 hr, 59 secOk! sec2str 86400        = 1 dOk! sec2str 6000000      = 9 wk, 6 d, 10 hr, 40 min

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.

Proc _CompoundDuration(7259)Proc _CompoundDuration(86400)Proc _CompoundDuration(6000000)End_CompoundDuration Param(1)             ' Print compound seconds  a@ = FUNC(_Compound(a@, 604800, _wk))  a@ = FUNC(_Compound(a@, 86400, _d))  a@ = FUNC(_Compound(a@, 3600, _hr))  a@ = FUNC(_Compound(a@, 60, _min))  If a@ > 0 Then Print a@;" sec";      ' Still seconds left to print?  PrintReturn_Compound Param(3)  Local(1)  d@ = a@/b@                           ' Get main component  a@ = a@%b@                           ' Leave the rest  If d@ > 0 Then                       ' Print the component    Print d@;    Proc c@    If a@ > 0 Then      Print ", ";                      ' If something follows, take    EndIf                              ' care of the comma  EndIfReturn (a@)_wk  Print " wk";  : Return_d   Print " d";   : Return_hr  Print " hr";  : Return_min Print " min"; : Return
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min0 OK, 0:94

Uiua

Works with:Uiua version 0.18.0

Run it in Uiua Pad!

# Builds a string representation of a time periodUnits     ← {"second" "minute" "hour" "day" "week"}Durations ← [60 60 24 7 9999]Parts  ← ⇌◌∧(⊙⊂⊃(⌊÷|◿))Durations⊙[]             # seconds -> [S M H D W]Sunit  ← /⍚$"_ _"⍥⍜(⊡1|⍚⊂⊙@s)≠□"1"⊢.            # Stringify a unit, add plurals.String ← /◇$"_, _"⇌≡Sunit▽⊃(±|⍉⇌⊟Units°⋕) Parts # Build full string.≡(&p$"_s   \t= _"⟜String)[7259 86400 6000000 14000000 31449599 31449601]
Output:
7259s           = 2 hours, 59 seconds86400s          = 1 day6000000s        = 9 weeks, 6 days, 10 hours, 40 minutes14000000s   = 23 weeks, 1 day, 53 minutes, 20 seconds31449599s   = 51 weeks, 6 days, 23 hours, 59 minutes, 59 seconds31449601s   = 52 weeks, 1 second

Vale

Works with:Vale version 0.2.0
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;}

VBA

PrivateFunctioncompound_duration(ByValsecondsAsLong)AsStringminutes=60hours=60*minutesdays_=24*hoursweeks=7*days_DimoutAsStringw=seconds\weeksseconds=seconds-w*weeksd=seconds\days_seconds=seconds-d*days_h=seconds\hoursseconds=seconds-h*hoursm=seconds\minutess=secondsModminutesout=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","")IfRight(out,2)=", "Thencompound_duration=Left(out,Len(out)-2)Elsecompound_duration=outEndIfEndFunctionPublicSubcstcd()Debug.Printcompound_duration(7259)Debug.Printcompound_duration(86400)Debug.Printcompound_duration(6000000)EndSub
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

VBScript

Functioncompound_duration(n)DoUntiln=0Ifn>=604800Thenwk=Int(n/604800)n=n-(604800*wk)compound_duration=compound_duration&wk&" wk"EndIfIfn>=86400Thend=Int(n/86400)n=n-(86400*d)Ifwk>0Thencompound_duration=compound_duration&", "EndIfcompound_duration=compound_duration&d&" d"EndIfIfn>=3600Thenhr=Int(n/3600)n=n-(3600*hr)Ifd>0Thencompound_duration=compound_duration&", "EndIfcompound_duration=compound_duration&hr&" hr"EndIfIfn>=60Thenmin=Int(n/60)n=n-(60*min)Ifhr>0Thencompound_duration=compound_duration&", "EndIfcompound_duration=compound_duration&min&" min"EndIfIfn>0ThenIfmin>0Thencompound_duration=compound_duration&", "EndIfcompound_duration=compound_duration&", "&n&" sec"n=0EndIfLoopEndFunction'validating the functionWScript.StdOut.WriteLinecompound_duration(7259)WScript.StdOut.WriteLinecompound_duration(86400)WScript.StdOut.WriteLinecompound_duration(6000000)
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

Wren

varduration=Fn.new{|s|if(s<1)return"0 sec"vardur=""vardivs=[7,24,60,60,1]varunits=["wk","d","hr","min","sec"]vart=divs.reduce{|prod,div|prod*div}for(iin0...divs.count){varu=(s/t).floorif(u>0){dur=dur+"%(u)%(units[i]), "s=s%t}t=t/divs[i]}if(dur.endsWith(", "))dur=dur[0..-3]returndur}for(sin[7259,86400,6000000])System.print(duration.call(s))
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

XPL0

char Str(80);func Duration(Sec); \Convert seconds to compound durationint  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+LFI:= 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));]
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

zkl

fcn toWDHMS(sec){  //-->(wk,d,h,m,s)   r,b:=List(),0;   foreach u in (T(60,60,24,7)){      sec,b=sec.divr(u);   // aka divmod      r.append(b);   }   r.append(sec).reverse()}

Or, if you like to be concise:

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();}

were the ":" op takes the left result and stuffs it into the "_" position.

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();}
Output:
2 hr, 59 sec1 d9 wk, 6 d, 10 hr, 40 min

ZX Spectrum Basic

Translation of:AWK
10LETm=60:LETh=60*m:LETd=h*24:LETw=d*720DATA10,7259,86400,6000000,0,1,60,3600,604799,604800,69486130READn40FORi=1TOn50READs60LETnweek=0:LETnday=0:LETnhour=0:LETnmin=0:LETnsec=0:LETs$=""70PRINTs;" = ";80IFs>=wTHENLETnweek=INT(s/w):LETs=FNm(s,w)90IFs>=dTHENLETnday=INT(s/d):LETs=FNm(s,d)100IFs>=hTHENLETnhour=INT(s/h):LETs=FNm(s,h)110IFs>=mTHENLETnmin=INT(s/m):LETs=FNm(s,m)120LETnsec=INT(s)130IFnweek>0THENLETs$=s$+STR$nweek+" wk, "140IFnday>0THENLETs$=s$+STR$nday+" d, "150IFnhour>0THENLETs$=s$+STR$nhour+" hr, "160IFnmin>0THENLETs$=s$+STR$nmin+" min, "170IFnsec>0THENLETs$=s$+STR$nsec+" sec"180IFs$<>""THENIFs$(LENs$-1)=","THENLETs$=s$(TOLENs$-2)190PRINTs$200NEXTi210STOP220DEF FNm(a,b)=a-INT(a/b)*b
Retrieved from "https://rosettacode.org/wiki/Convert_seconds_to_compound_duration?oldid=396605"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2026 Movatter.jp