28
\$\begingroup\$

The following is inspired by a question that came up on Stack Overflow today.

Given a number of microseconds, 0 <= n <= 86400000000 (e.g. 12345678900), output a formatted string hh:mm:ss:000:000, e.g. 03:25:45:678:900.

          0 -> '00:00:00:000:000'
12345678900 -> '03:25:45:678:900'
86400000000 -> '24:00:00:000:000'

I have a solution in Python in 209 bytes, but can it go lower?

\$\endgroup\$
7
  • 1
    \$\begingroup\$ I realise now that this isn't really a standard format for writing times, and hh:mm:ss.000000 would probably have been better (and easier). Still, can't go changing it now. \$\endgroup\$
    – Sam
    Jul 6, 2015 at 21:43
  • 1
    \$\begingroup\$ Out of curiosity, what was the SO post? \$\endgroup\$ Jul 6, 2015 at 23:25
  • \$\begingroup\$ @DigitalTrauma stackoverflow.com/questions/31251377 by a relatively new user. A correct answer had already been chosen, I was just playing around in IDLE and came up with a grotesque-looking dictionary comprehension that wasn't a particularly good answer to the question. Someone saw it and pointed out this site in a comment. I came here, wrote a question (slightly different to the SO post), and also wrote a much improved version of my answer (which I haven't posted, and which is now redundant to all the much more compact and imaginative answers below). \$\endgroup\$
    – Sam
    Jul 7, 2015 at 7:19
  • \$\begingroup\$ Is there a limit on the number of hours in the input? \$\endgroup\$
    – FUZxxl
    Jul 7, 2015 at 10:19
  • \$\begingroup\$ Yes, arbitrarily I made it <= 86400000000 microsec, so <= 24 hours. \$\endgroup\$
    – Sam
    Jul 7, 2015 at 10:25

19 Answers 19

15
\$\begingroup\$

Python 2, 82 79 bytes

n=input()
o=""
for k in[1000]*2+[60]*3:o=":%0*d"%(k%7/2,n%k)+o;n/=k
print o[1:]

Builds the string, iterating through a series of divmods. The only fancy bit is the %7/2, which maps 1000 -> 3 and 60 -> 2.

\$\endgroup\$
6
\$\begingroup\$

Pyth, 31 bytes

j\:_m>l`td+"00"%~/QddCM"ϨϨ<<<

Try it online: Demonstration

Explanation:

                                 implicit: Q = input number
                       "ϨϨ<<<   string "ϨϨ<<<" (5 chars but 7 bytes)
                     CM          convert each to number => [1000, 1000, 60, 60, 60]
    m                            map each number d to:
                 /Qd                divide Q by d
                ~                   and update Q with the new value
               %~ Q d               but use the old value to calculate Q mod d
          +"00"                     add the result to the string "00"
     >                              but only take the last 
      l`td                          len(str(d-1)) chars
   _                             revert order
j\:                              join the strings with ":"s
\$\endgroup\$
5
\$\begingroup\$

Bash + coreutils, 61

Shortest "mainstream" language so far...

a=%02d:
printf $a$a$a%03d:%03d `dc -e$1\ A00~rA00~r60~r60~rf`

Test output:

$ for t in 0 12345678900 86400000000; do ./usec.sh $t; echo; done
00:00:00:000:000
03:25:45:678:900
24:00:00:000:000
$ 
\$\endgroup\$
4
\$\begingroup\$

CJam, 37 35 34 bytes

This is prettty long .. Golfing now..

ri[1e3_60__]{:ImdsIBb,0e[':@}%W%2>

UPDATE: 1 byte saved thanks to @Sp3000

Try it online here

\$\endgroup\$
4
\$\begingroup\$

C, 97 bytes

q=1000,s=60;
#define f(n)printf("%02d:%02d:%02d:%03d:%03d",n/s/s/q/q,n/s/q/q%s,n/q/q%s,n/q%q,n%q)

Test Code:

int main(int intc, char **argv)
{
    long long n = atoll(argv[1]);
    f(n);
}
\$\endgroup\$
8
  • 1
    \$\begingroup\$ Answers in C are supposed to be a complete, program; not a snippet. \$\endgroup\$
    – NobodyNada
    Jul 7, 2015 at 1:58
  • \$\begingroup\$ It is not mentioned in the question. Is there some sort of global requirements? \$\endgroup\$
    – some user
    Jul 7, 2015 at 2:18
  • \$\begingroup\$ Loopholes that are forbidden by default \$\endgroup\$
    – NobodyNada
    Jul 7, 2015 at 2:20
  • \$\begingroup\$ No. If you read the answer, it is just using C as an example. The rule would have applied to every language. Also, the answer is hotly disputed - see the highest rated comment. The bottom line is the Question needs to state it clearly if a full program is required. \$\endgroup\$
    – some user
    Jul 7, 2015 at 2:26
  • 3
    \$\begingroup\$ Lots of answers on this site use functions instead of full programs - for example I don't think I have ever seen a Java answer that was a complete program... \$\endgroup\$ Jul 7, 2015 at 23:45
4
\$\begingroup\$

q (34)

I'm sure it can be shorter

":"sv 0 8 11__[;8]15$2_($)16h$1e3*

e.g.

q)f:":"sv 0 8 11__[;8]15$2_($)16h$1e3*
q)f 12345678900
"03:25:45:678:900"
\$\endgroup\$
4
  • 4
    \$\begingroup\$ any online compilers ? in other words - How do I run it as a lazy person ? \$\endgroup\$
    – Optimizer
    Jul 6, 2015 at 21:32
  • \$\begingroup\$ 32 bit version is available for free at kx.com \$\endgroup\$
    – skeevey
    Jul 6, 2015 at 21:32
  • \$\begingroup\$ good spot. unfortunately the fix adds a few characters \$\endgroup\$
    – skeevey
    Jul 6, 2015 at 21:43
  • 1
    \$\begingroup\$ you can cut more bytes here ":"sv 0 8 11__[;8]15$2_($)"n"$1e3* \$\endgroup\$ Jul 7, 2015 at 10:57
3
\$\begingroup\$

Julia, 110 96 95 bytes

t->(o="";for i=int([36e8,6e7,1e6,1e3,1]) x,t=t÷i,t%i;o*=lpad(x,i>1e3?2:3,0)*":"end;o[1:end-1])

This creates an unnamed function that accepts an integer as input and returns a string. To call it, give it a name, e.g. f=t->....

Ungolfed + explanation:

function f(t)
    # Initialize an output string
    o = ""

    # Loop over an array consisting of the number of microseconds in
    # an hour, minute, second, millisecond, and microsecond
    for i = int([36e8, 6e7, 1e6, 1e3, 1])

        # Get the quotient and remainder for microseconds into t,
        # setting t to be the remainder
        x, t = t ÷ i, t % i

        # Left-pad x with zeroes and append it to the output
        o *= lpad(x, i > 1e3 ? 2 : 3, 0) * ":"
    end

    # o has a trailing :, so return everything but the last character
    o[1:end-1]
end

Examples:

julia> f(12345678900)
"03:25:45:678:900"

julia> f(0)
"00:00:00:000:000"

julia> f(86400000000)
"24:00:00:000:000"
\$\endgroup\$
1
  • \$\begingroup\$ Nice one. You get my vote because you inspired my Matlab answer :-) \$\endgroup\$
    – Hoki
    Jul 7, 2015 at 10:21
3
\$\begingroup\$

C#, 179 175 Bytes

When you have builtins at your disposal, why not use 'em?

static void Main(string[]a){var t=TimeSpan.FromTicks(long.Parse(Console.ReadLine())*10);Console.Write(t.ToString((t.Days<1?"hh":@"\2\4")+@"\:mm\:ss\:ffffff").Insert(12,":"));}

With better formatting:

static void Main(string[]a){
    var t = TimeSpan.FromTicks(long.Parse(Console.ReadLine())*10);
    Console.Write(t.ToString((t.Days<1?"hh":@"\2\4")+@"\:mm\:ss\:ffffff").Insert(12,":"));
    Console.Read();
}
\$\endgroup\$
3
\$\begingroup\$

Excel, 65 63 characters

Assuming your microseconds is in A1:

=TEXT(A1/50/1200^3,"[HH]:mm:ss:")&RIGHT(TEXT(A1,"000\:000"),7)

Output:

        A              B
1            0  00:00:00:000:000
2  12345678900  03:25:46:678:900
3  86400000000  24:00:00:000:000
\$\endgroup\$
2
\$\begingroup\$

Perl, 141 78 bytes

printf"%02d"x3.%03d:%03d",$_/36e8,$_/6e7%60,$_/1e6%60,$_/1e3%1e3,$_‌​%1e3

77 bytes of code, +1 for the -n flag. Run with:

echo 12345678900 | perl -ne'printf"%02d"x3.%03d:%03d",$_/36e8,$_/6e7%60,$_/1e6%60,$_/1e3%1e3,$_‌​%1e3'

Thanks to Thomas Kwa and chilemagic for cutting my code size nearly in half.

\$\endgroup\$
5
  • \$\begingroup\$ I think 3600000000 can be 36e8. \$\endgroup\$
    – lirtosiast
    Jul 6, 2015 at 20:04
  • \$\begingroup\$ Instead of chomp($n=<STDIN>); you can run it as a one-liner with the -n flag (which counts as 1 character). You also don't need the int(..) around each $_. Applying Thomas's tip too we can get it down to echo 12345678900 | perl -ne'printf"%02d:%02d:%02d:%03d:%03d\n",$_/36e8,$_/6e7%60,$_/1e6%60,$_/1e3%1e3,$_%1e3' and there might even be a shorter way too! \$\endgroup\$
    – hmatt1
    Jul 6, 2015 at 22:18
  • \$\begingroup\$ You don't need the \n in the output string either. You can also replace the string with "%02d:"x3 ."%03d:%03d" \$\endgroup\$
    – hmatt1
    Jul 6, 2015 at 22:23
  • \$\begingroup\$ @chilemagic Does using "echo" count as an increase in bytes? \$\endgroup\$ Jul 7, 2015 at 17:22
  • \$\begingroup\$ @ASCIIThenANSI it doesn't because it isn't part of your program. The characters you would count are the ones between the single quotes, i.e. printf"%02d:%02d:%02d:%03d:%03d\n",$_/36e8,$_/6e7%60,$_/1e6%60,$_/1e3%1e3,$_‌​%1e3 and then you add an additional byte for the -n flag. If you used -nle for example, that would count as an additional 2 (for the n and the l). You get the - and the e (or E if you need to use say) for free. \$\endgroup\$
    – hmatt1
    Jul 7, 2015 at 17:28
1
\$\begingroup\$

CoffeeScript, 127 bytes

Took the approach in ASCIIThenANSI's answer. It's too bad that the JavaScript Console API doesn't have format placeholders for padding numbers.

p=(a,b)->('00'+~~a).slice -b||-2
f=(t)->console.log '%s:%s:%s:%s:%s',p(t/36e8),p(t/6e7%60),p(t/1e6%60),p(t/1e3%1e3,3),p t%1e3,3
\$\endgroup\$
1
\$\begingroup\$

Matlab - 88 89 bytes

Gained one byte with a solution without using the built in function:

n=[36e8,6e7,1e6,1e3];f=@(t)sprintf('%02d:%02d:%02d:%03d:%03d',fix([t mod(t,n)]./[n 1]))

Create an inline function which takes a numeric input argument t and return a string.

it uses a vectorized combination of fix and mod to separate the time elements, then display.

it's a bit frustrating that the formatting of the output string takes so much, more than the calculations themselves ...

Test:

for t=[0 12345678900 86400000000]
    f(t)
end

ans =
00:00:00:000:000
ans =
03:25:45:678:900
ans =
24:00:00:000:000

89 bytes version:

f=@(t)sprintf('%s:%03d:%03d',datestr(fix(t/1e6)/86400,13),fix(mod(t,1e6)/1e3),mod(t,1e3))

It splits the number, uses a built-in function for the hh:mm:ss part, which cannot deal with microseconds so the string is completed with combination of fix and mod operations

\$\endgroup\$
1
\$\begingroup\$

Powershell,153

$t=[timespan]::FromTicks(($a=$args[0]));"{0:D2}:{1:D2}:{2:D2}:{3:D3}:{4:000}"-f
[int]($t.TotalHours),$t.Minutes,$t.Seconds,$t.Milliseconds,(($a%1e4)/10)

Usage

powershell -nologo .\modprintsec.ps1 123456789000    
03:25:45:678:900   
powershell -nologo .\modprintsec.ps1 864000000000   
24:00:00:000:000   
powershell -nologo .\modprintsec.ps1 0   
00:00:00:000:000 
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 128 118 116 111 bytes

There is probably some golfing potential in this.

f=t=>(t<864e8?new Date(t/1e3).toJSON().slice(11,-1):`24:00:00:000`).replace(`.`,`:`)+':'+('00'+t%1e3).slice(-3)

Demo

It is ES6 so Firefox only, for now anyways:

f=t=>(t<864e8?new Date(t/1e3).toJSON().slice(11,-1):`24:00:00:000`).replace(`.`,`:`)+':'+('00'+t%1e3).slice(-3)

// DEMO
document.body.innerHTML += '<br>' + f(0);
document.body.innerHTML += '<br>' + f(12345678020);
document.body.innerHTML += '<br>' + f(86400000000);

\$\endgroup\$
3
  • \$\begingroup\$ The first check is not needed, as the question is explicit: 0 <= n <= 86400000000 \$\endgroup\$
    – edc65
    Jul 7, 2015 at 9:06
  • \$\begingroup\$ @edc65 Without the first check I can only get a range of 0 ≤ n < 86400000000, as 8.64e10 would roll over to the next day. \$\endgroup\$ Jul 7, 2015 at 14:34
  • \$\begingroup\$ Oh right, I missed that. toJSON() instead of toISOString()? \$\endgroup\$
    – edc65
    Jul 7, 2015 at 20:18
1
\$\begingroup\$

F#, 111 92 102 bytes

First iteration: Base idea.

Second iteration: Smaller constants

Third iteration: Correct formatting for single digit portions.

Note this function must be given an int64 to work.

let s,t=60L,1000L
let f n=sprintf"%02d:%02d:%02d:%03d:%03d"(n/s/s/t/t)(n/s/t/t%s)(n/t/t%s)(n/t%t)(n%t)

Example outputs:

f 0L           -> "00:00:00:000:000"
f 12345678900L -> "03:25:45:678:900"
f 86400000000L -> "24:00:00:000:000"
\$\endgroup\$
1
\$\begingroup\$

C, 113 103 105 bytes

EDIT: shoved off some more bytes

FIX: removed long type, thanks to some user

Not the shortest C answer, but I had some fun with carriage returns so I felt like someone might like this.

i,k,p=16;
#define f(n)for(;i<5;p-=i++<2?4:3)k=i<2?1000:60,printf("%0*d%c\r",p,n%k,i?58:13),n/=k;puts("");

Call it like:

int main() {
    long long n = 12345678900;
    f(n);

    return 0;
}
\$\endgroup\$
2
0
\$\begingroup\$

PHP - 115 102 bytes

A solution in 155 bytes (wrapped here on 3 lines for readability):

$a=$argv[1];
$h=($a-($m=($a=($a-($s=($a=($a-($t=($a=($a-($u=$a%1000))/1000)%1000))/1000)%60))/60)%60))/60;
printf("%02d:%02d:%02d:%03d:%03d",$h,$m,$s,$t,$u);

The second line computes (from inside to outside) the exact values of the components starting with the microseconds.

The shorter version (115 bytes, wrapped on two lines for readability):

$u=$argv[1];$h=($m=($s=($t=$u/1000)/1000)/60)/60;
printf("%02d:%02d:%02d:%03d:%03d",$h,$m%60,$s%60,$t%1000,$u%1000);

It also uses embedded assignments to compute the convert the input number of microseconds in milliseconds, seconds, minutes and hours using floating point numbers. The modulus operator (%) and the decimal number format (%d) of printf() is then used to force them to integer numbers (the fractional part is ignored).

Another solution that uses the date functions (102 bytes)

$u=$argv[1];
echo gmdate("H:i:s",strtotime("@".substr($u,0,-6))),":",substr($u,-6,3),":",substr($u,-3);

The hours:minutes:seconds part is handled by the PHP date functions gmdate() and strtotime(), the milli- and micro-seconds are extracted as strings from the input value.

Usage:

$ php -r '$u=$argv[1];echo gmdate("H:i:s",strtotime("@".substr($u,0,-6))),":",substr($u,-6,3),":",substr($u,-3);' 7198898787; echo
01:59:58:898:787
\$\endgroup\$
0
\$\begingroup\$

Java, 215 bytes

String f(long n){return p(n/3600000000l,2)+":"+p(n/60000000%60,2)+":"+p(n/1000000%60,2)+":"+p(n/1000%1000,3)+":"+p(n%1000,3);}String p(long n,int i){String s=String.valueOf(n);while(s.length()<i){s="0"+s;}return s;}

Method f does some calculations on n to work out the hours, minutes etc. and delegates to method p to format each value correctly.

Formatted:

String f(long n) {
    return p(n / 3600000000l, 2) + ":" + p(n / 60000000 % 60, 2) + ":" 
            + p(n / 1000000 % 60, 2) + ":" + p(n / 1000 % 1000, 3) + ":" + p(n % 1000, 3);
}

String p(long n, int i) {
    String s = String.valueOf(n);
    while (s.length() < i) {
        s = "0" + s;
    }
    return s;
}

Usage:

public void demo() {
    long n = 12345678900l;
    System.out.println(f(n));
}
\$\endgroup\$
-1
\$\begingroup\$

Ruby - 82 Bytes

puts (t=Time.at(0,gets.to_i)).strftime("%2H:%2M:%2S:%3L:#{(t.usec%1000).to_s.rjust(3,?0)}")
\$\endgroup\$
1
  • 2
    \$\begingroup\$ But I counted 91 bytes. It also only works in the UTC timezone. \$\endgroup\$
    – jimmy23013
    Jul 7, 2015 at 20:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.