The idea is this: Write a function to print the length of time from now/today's date (at the time the function is called) until a date supplied as an argument.


  • Input date will always be tomorrow or later, in the future.
  • Input date will never be more than 10 years in the future.


  • Output must be in this format: "[z year(s)], [x month(s)], y day(s) until -Input Date-"
  • Output time frame (day/month/year) must be pluralized correctly. i.e. 1 month, not 1 months
  • Input can be in whichever date format you prefer (3/15/12 - March 15, 2012 - 2012.03.15).

Example: Assuming program is run on March 15, 2012:

  • Input date of 3/20/12 = 5 days until 3/20/12
  • NOT Input date of 4/16/12 = 1 month, 1 days until 3/20/12
  • Input date of 2012.04.20 = 1 month, 5 days until 2012.04.20
  • NOT Input date of 2012.04.20 = 36 days until 2012.04.20
  • Input date of 10/31/17 = 5 years, 7 months, 16 days until 10/31/17
  • Input date of 3/15/13 = 1 year until 3/15/13

This is code golf, so shortest length code wins.

I suppose for the sake of having a deadline, I will be selecting an answer on:

March 23, 2012!

(This is my first CG question, so I'll be happy to correct any question errors on my part!)

  • 3
    \$\begingroup\$ Wolfram|Alpha 10 chars: now until <input time> :p \$\endgroup\$
    – Griffin
    Commented Mar 15, 2012 at 22:16
  • 3
    \$\begingroup\$ @Griffin 4 chars: now-<input time> \$\endgroup\$
    – PhiNotPi
    Commented Mar 15, 2012 at 22:23
  • 1
    \$\begingroup\$ @PhiNotPi well played, good sir. \$\endgroup\$
    – Griffin
    Commented Mar 15, 2012 at 22:24
  • 2
    \$\begingroup\$ Is it okay to say "1 days until 3/16/12"? \$\endgroup\$
    – MrZander
    Commented Mar 15, 2012 at 23:32
  • 1
    \$\begingroup\$ Welcome to CodeGolf.SE. Every question should be tagged to indicate the class of challenge that is being presented (i.e. if you mean the least characters you want [code-golf]), because we entertain other types of challenges as well, as long as they have an objective winning standard. I'll do this one for you. BTW--Nicely specified. \$\endgroup\$ Commented Mar 16, 2012 at 0:50

7 Answers 7


R, 99 characters

I know it is sort of cheating, but R is all about its packages and lubridate is so convenient for this kind of tasks!



[1] 5 years, 7 months and 16 days 
5 years, 7 months and 16 days  until 10/31/2017

Python + dateutil, 331 bytes

from dateutil import*
from datetime import*
def f(s):
 if'/'in s:m,y,d=map(int,s.split('/'))
 return f"{Y} year{'s'*(Y>1)}, "*(Y>0)+f"{M} month{'s'*(M>1)}, "*(M>0)+f"{D} day{'s'*(D>1)} "*(D>0)+"until "+s

PHP, 315 characters

function p($z)
$s="s ";
echo ($y?$y." year".$s[$y<2]:"")." ".($m?$m." month".$s[$m<2]:"")." ".($d?$d." day".$s[$d<2]:"")." until ".$z;



Takes dates in a dd/mm/yyyy format. I've used Griffin's month length calculation(again), though I had to stick extra brackets in it to make the precedence work properly. I've also left some line-breaks in to make it a little easier to read.


Ruby (213)

takes dates in any format Date.parse accepts. Tried just with yyyy-mm-dd

def u s
f=Date.parse s
[[0,'year'],[0,'month'],[0,'day']].map{|c,n| while t<f 
c,t=c-1,t.send("prev_#{n}")if t>f
[c,n+(c>1??s:'')]*' 'if c>0}.compact*', '+' until '+s

to also get weeks, add:

['prev_','next_'].each{|n|Date.send(:define_method,n+'week'){send n+'day',7}}

and [0,'week'], (between month and day). days will then always be < 7

  • \$\begingroup\$ which ruby version are you using.... I tried to run your code on ruby1.9.2p0, but it gives me error uninitialized constant Object::Date (NameError)... I think you are using the Rails Date class \$\endgroup\$
    – Rohit
    Commented Mar 22, 2012 at 12:09
  • \$\begingroup\$ @Rohit 1.9.3, not using Rails stuff. Date rdoc \$\endgroup\$
    – jsvnm
    Commented Mar 23, 2012 at 8:16
  • \$\begingroup\$ I saw the doc earlier.. but was confused on the error I was getting... I am still unable to figure out why I am getting this error. I am on windows 7 64-bit, ruby192p0 \$\endgroup\$
    – Rohit
    Commented Mar 23, 2012 at 21:57
  • \$\begingroup\$ @rohit try with 193? \$\endgroup\$
    – jsvnm
    Commented Mar 24, 2012 at 10:15

VBA: 766 631 Chars

Thanks to mellamokb for helping shorten up the string creation and IIf.

Function k(i)
e=" month"
For y=0 To 10
If Year(DateAdd("yyyy",-1*y,i))=Year(n) Then Exit For
For m=0 To z
If Month(DateAdd("m",-1*m,i))=r Then Exit For
If y Then a=y & " year" & Left(g,y-1)
a=IIf((m Or d) And y,a & ",",a)
If m Then b=IIf(d,m & e & Left(g,m-1) & ",",m & e & Left(g,m-1))
If d Then c=IIf(d>1,d & " days",d & " day")
k=Trim(Trim(a & " " & b) & " " & c) & " until " & i & "."
End Function

I know VBA definitely does not lend itself to code golfing as well as some other languages, but it's what I'm good (not expert) at. :-)

This has been a fun exercise for me!

  • 1
    \$\begingroup\$ It's not entirely VBA's fault, there are some good ways to combine logic in your code :) For example, If y > 0 Then a = y & " year,":If y > 1 Then a = y & " years," could be combined together to a = y & " year" & Left("s", y - 1) & "," \$\endgroup\$
    – mellamokb
    Commented Mar 16, 2012 at 14:23
  • \$\begingroup\$ @mellamokb Very good. I'll take a look at that and repost! \$\endgroup\$
    – Gaffi
    Commented Mar 16, 2012 at 14:27
  • \$\begingroup\$ I had an issue with some test cases, namely 1 year, 1 month, 1 day. I have corrected this in the answer. It actually made for shorter code! \$\endgroup\$
    – Gaffi
    Commented Mar 16, 2012 at 17:39
  • \$\begingroup\$ And after posting the update, I see that I can change If v < w Then d = w - v:If v = w Then d = 0 to If v <= w Then d = w - v for a savings of an additional 20 characters. I'll update the answer if I have a more significant change to post. \$\endgroup\$
    – Gaffi
    Commented Mar 16, 2012 at 17:59
  • \$\begingroup\$ I imagine I can do this better with arrays... I will take another look and possibly add another answer... \$\endgroup\$
    – Gaffi
    Commented Mar 18, 2012 at 7:09

JavaScript (ES6), 125 bytes

Since the answer by Paolo used an external library, I shall do the same. Node.js is all about NPM packages and moment + HumanizeDuration is so convenient for this task!

Node environments

m=require('moment'),f=d=>console.log(require('humanize-duration')(m(d).diff(m()),{units:['y','mo','d'],round:1})+' until '+d)

Browser environment

Since the libraries declare global variables, it's actually a bit shorter (102 bytes). It's not clear whether I need to include the script tags required to load in the third-party JavaScript, so I will count the Node one officially.

f=d=>console.log(humanizeDuration((m=moment)(d).diff(m()),{units:['y','mo','d'],round:1})+' until '+d)

CoffeeScript, also 125 bytes

f=(d)->console.log require('humanize-duration')((m=require 'moment')(d).diff(m()),{units:['y','mo','d'],round:1})+' until '+d

PHP, 151 chars

function p($z){$n=date_create(date('Y-m-d'));$d=date_create($z);$i=date_diff($n,$d);print($i->format('%R%y years, %m months, and %a days until '.$z));}
  • \$\begingroup\$ It is missing the plurals and does not count correctly, because format() does not subtract the days from the months... I had a similar solution with PHP as well. \$\endgroup\$
    – powtac
    Commented May 15, 2012 at 22:18
  • \$\begingroup\$ This is my PHP solution, but still lacks of the previously mentioned error: echo date_diff(new DateTime(),new DateTime($argv[1]))->format('%yyears, %mmonths, %a days'); Its 92 chars long, when called on the command line. \$\endgroup\$
    – powtac
    Commented May 15, 2012 at 22:23

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.