9
\$\begingroup\$

What you need to do to win this challenge is to write the shortest "timeago" script that outputs the number of decades, years, weeks, days, hours, minutes, and seconds between a given Unix timestamp and the time the script is run.

You must give the time difference in "lowest terms", e.g. 1 week not 7 days, 9 years not 0 decades 9 years. You also must use plural forms correctly, e.g. 1 day not 1 days.

Your script must be accurate to within plus or minus 1 second (so the exact second rounding method is unimportant).

Time Equivalency Table
1 decade = 10 years
1 year = 31536000 seconds (not technically correct but close enough)
1 week = 7 days
1 day = 24 hours
1 hour = 60 minutes
1 minute = 60 seconds

The output should be of the form

A decade(s) B year(s) C week(s) D day(s) E hour(s) F minute(s) G second(s)

where A...G are all non-negative integers and the s is only there for plurals.

Notes

  • The timestamp will always be a time from the past. It may be negative.
  • Input and output may be anything reasonable: stdin/stdout, function input and return value, etc.
  • You may not use any tools that already do this. i.e. if your language has a timesince(timestamp) function built in you may not use that function.

I have vastly edited this to make it clearer in hopes to assuage the somewhat silly battle between new users with unclear questions and old users who require perfection. It was not a terrible question (though now it may be too similar to this).

Given that enough time is passed since the last answer, I declare Three If By Whiskey with its 177 bytes Ruby implementation the winner of this context!

\$\endgroup\$
  • 2
    \$\begingroup\$ "In the case of Javascript JQuery is forbidden :P Everything else is ok." -- is Zepto allowed, then? \$\endgroup\$ – John Dvorak Aug 23 '14 at 17:40
  • 4
    \$\begingroup\$ The spec is kinda poor. Please provide an exact definition of what it is supposed to do - an example implementation doesn't suffice. \$\endgroup\$ – John Dvorak Aug 23 '14 at 17:40
  • 1
    \$\begingroup\$ Is Timeago some new scripting language? Is updating every 30 seconds optional (as stated in one place) or a requirement (as stated in another)? What I/O mechanisms are acceptable? What rounding should be used? In particular, how does rounding interact with variable-length time periods such as calendar months and years? Some of these may imply follow-up questions depending on your answers. \$\endgroup\$ – Peter Taylor Aug 23 '14 at 18:00
  • 1
    \$\begingroup\$ @Abdossam I know we all seem pretty fussy but it's because questions on this site are supposed to have objective winning criteria and a clear spec. \$\endgroup\$ – Calvin's Hobbies Aug 23 '14 at 19:22
  • 1
    \$\begingroup\$ Two suggestions: 1) Leave out the HTML part. I guess nobody want's to write an HTML parser before being able to tackle the real task of printing times. 2) Make clear that you restrict to "second(s)", "minute(s)", "hour(s)" and "day(s)". You might add "week(s)" if you wish. But months and years are not that clearly defined (28-31 days / 365 or 366 days...). This should fix the major concerns with this question in my point of view. \$\endgroup\$ – Falko Aug 23 '14 at 20:10
2
\$\begingroup\$

Ruby, 184 177

->n{x=Time.now.to_i-n;d=[3650*y=86400,365*y,7*y,y,3600,60,1];(0..6).map{|i|c=x/d[i];(x%=d[i]*c;"#{c} #{%w[decade year week day hour minute second][i]}#{c<2?'':'s'}")if c>0}*' '}

There's nothing particularly clever here, but I suspect it's still very close to optimal.

Example run

p ->n{x=Time.now.to_i-n;d=[3650*y=86400,365*y,7*y,y,3600,60,1];(0..6).map{|i|c=x/d[i];(x%=d[i]*c;"#{c} #{%w[decade year week day hour minute second][i]}#{c<2?'':'s'}")if c>0}*' '}[0]
"4 decades 4 years 41 weeks 3 days 14 hours 20 minutes 48 seconds"
\$\endgroup\$
2
\$\begingroup\$

J , 165

;' '&,@":&.>@((#~([:*&>{."1))@((;:' decades years weeks days hours minutes seconds')(],.([}.~[:-1=])&.>)<"0@(_ 10 52 7 24 60 60&#:)@(-~([:".@}:[:2!:0'date +%s'"_))))

Can probably be golfed more. Uses a shell call to date for getting the current unix epoch time, since Unix epoch is unavailable in J.

Example run:

;' '&,@":&.>@((#~([:*&>{."1))@((;:' decades years weeks days hours minutes seconds')(],.([}.~[:-1=])&.>)<"0@(_ 10 52 7 24 60 60&#:)@(-~([:".@}:[:2!:0'date +%s'"_)))) 0
4 decades 4 years 41 weeks 3 days 12 hours 54 minutes 1 second
\$\endgroup\$
2
\$\begingroup\$

Python - 183

import time;t=int(time.time()-input());d=86400
for f,u in zip((3650*d,365*d,7*d,d,3600,60,1),'decade year week day hour minute second'.split()):
 if t/f:print`t/f`,u+'s'*(t/f>1),;t%=f

Output for a timestamp 999996400 seconds in the past:

3 decades 1 year 37 weeks 46 minutes 39 seconds
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 392

t=function(c){i=function(){var a=+new Date/1e3-c,b=document;29>a?b.write("just now"):60>a?b.write((a|0)+" seconds ago"):60<a&&120>a?b.write("1 minute ago"):60>a/60?b.write((a/60|0)+" minutes ago"):60<a/60&&120>a/60?b.write("1 hour ago"):24>a/3600?b.write((a/3600|0)+" hours ago"):24<a/3600&&48>a/3600?b.write("1 day ago"):1<=a/86400&&b.write((a/86400|0)+" days ago")};i();setInterval(i,3e4)};

Also the unminified code for the curious ones

t = function(timestamp){

i = function() {
var diff = (+new Date/1e3)-(timestamp),
d = document;

    if( (diff) < 29) {

        d.write( 'just now' )
    }
    else if( diff < 60) {

        d.write( ( (diff) |0 ) + ' seconds ago' )
    }
    else if( diff > 60 && diff < 120) {
        d.write(  '1 minute ago' )
    }
    else if( (diff)/60 < 60) {
        d.write( ( (diff)/60 |0 ) + ' minutes ago' )
    }
    else if( (diff)/60 > 60 && (diff)/60 < 120) {
        d.write( '1 hour ago' )
    }
    else if( (diff)/3600 < 24) {
        d.write( ( (diff)/3600 |0 ) + ' hours ago' )
    }
    else if( (diff)/3600 > 24 && (diff)/3600 < 48) {
        d.write( '1 day ago' )
    }
    else if( (diff)/86400 >= 1) {
        d.write( ( (diff)/86400 |0 ) + ' days ago' )
    }
  }

i()

setInterval(i, 3e4)

}

It updates every 30 seconds and calculates both singular and plural.

To run it use t(unix_timestamp)

\$\endgroup\$
  • \$\begingroup\$ Shouldn't you use fat arrow notation? \$\endgroup\$ – proud haskeller Aug 24 '14 at 20:20
  • \$\begingroup\$ @user965091 Please avoid throwing around accusations without any proof via public comments on unrelated posts; if you think someone is using a sock account, flag a post of theirs for moderator attention. I see absolutely no reason to suspect any sockpuppetry here, and even if there was, such a discussion should not be had in public. \$\endgroup\$ – Doorknob Aug 30 '14 at 19:08
  • \$\begingroup\$ @user965091 I don't see how any of the comments here could be considered "provocations." In any case, rudeness is not tolerated on the Stack Exchange network. Please try to remain courteous to all users, regardless of whether you suspect they are breaking the rules or for any other reason. \$\endgroup\$ – Doorknob Aug 30 '14 at 21:42
1
\$\begingroup\$

Javascript, 287

function p(e,n){return e>2?e+" "+n+"s ":e+" "+n+" "}function t(e){n=new Date/1e3,l=e-n,c=1,m=60,h=60*m,d=24*h,w=7*d,y=365*d,a=10*y,s="",v={a:"Decade",y:"Year",w:"Week",d:"Day",h:"Hour",m:"Minute",c:"Second"};for(i in v)k=v[i],i=window[i],(r=Math.floor(l/i))>0&&(s+=p(r,k)),l%=i;alert(s)}

to run use t(secondsInFuture);

\$\endgroup\$
  • 1
    \$\begingroup\$ When I run t(10) I just get an empty alert. \$\endgroup\$ – Ingo Bürk Aug 24 '14 at 12:11
  • \$\begingroup\$ Ugh, forgot the seconds, thanks @IngoBürk. To be clear its t(new Date()/1000 + 10); \$\endgroup\$ – Victory Aug 24 '14 at 21:13
  • \$\begingroup\$ Use ES6's fat arrow notation, also eval(i) is 2 bytes shorter than window[i]. \$\endgroup\$ – nyuszika7h Aug 25 '14 at 17:17
0
\$\begingroup\$

Javascript, 263

i=[315360000,31536000,604800,86400,3600,60,1];s=['decade','year','week','day','hour','minute','second'];function g(d){return p(parseInt((new Date().getTime()-d)/1000), 0);}function p(d,n){k=d-d%i[n];r=k/i[n];return (r>0?r+' '+s[n]+'(s) ':'')+(n<6?p(d-k,n+1):'');}

to run from the Javascript console, call

g(unixTimestamp);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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