12
\$\begingroup\$

The Rules

  • Each submission must be a full program.

  • The program must take input as two comma-separated dates in the form YYYY-MM-DD, and print the number of days that has passed since the second date to STDOUT as if today was the first date (if the second date would be in the future, output a negative number) plus an optional trailing newline, and nothing else. Assume both dates are in the Gregorian calendar.

  • The program must not write anything to STDERR.

    Note that there must be an interpreter so the submission can be tested.

  • Submissions are scored in bytes, in an appropriate (pre-existing) encoding, usually (but not necessarily) UTF-8. Some languages, like Folders, are a bit tricky to score - if in doubt, please ask on Meta.

  • This is , so shortest code wins

Examples

Input:

2015-12-03,2015-12-01

Output:

2

Input:

2015-12-03,2014-12-01

Output:

367

Input:

2015-12-03,2013-12-03

Output:

730
\$\endgroup\$
9
  • 1
    \$\begingroup\$ Related \$\endgroup\$
    – GamrCorps
    Dec 8, 2015 at 1:57
  • 1
    \$\begingroup\$ Are we allowed to use external libraries? Ones that are common in a given ecosystem but are not part of the standard lib? (For example, no one uses the JDK's Date APIs but JodaTime instead, even though it is technically an external library). \$\endgroup\$
    – Ruslan
    Dec 8, 2015 at 4:32
  • \$\begingroup\$ I assume everything uses UTC, since in my timezone the difference between 2015-11-01T00:00:00 and 2015-11-02T00:00:00 was only ~0.96 days (23 hours) due to daylight savings. You didn't mention anything about rounding fractional days, so you might want to clarify this in the question. (I think a lot of datetime libraries default to using local time.) \$\endgroup\$ Dec 8, 2015 at 15:51
  • 1
    \$\begingroup\$ What is the case for leap years? \$\endgroup\$ Dec 8, 2015 at 23:05
  • \$\begingroup\$ @TheCoffeeCup they must be handled \$\endgroup\$
    – user46167
    Dec 9, 2015 at 1:20

26 Answers 26

13
\$\begingroup\$

Bash + GNU utilities, 37

tr , \\n|date -f- +%s|dc -e??-86400/p

tr replaces the comma with a newline. date reads the newline separated dates and outputs the number of seconds since the Unix epoch that the passed-in date represents. These numbers are then put on the dc stack. Then its a simple matter of subtraction and divide by (24*60*60). In this case, dc stack-based RPN arithmetic evaluation is better than bc or bash $( ), mostly because the subraction-before-division needs no parentheses.

Input via STDIN:

$ echo 2015-12-3,2015-12-1 | ./longago.sh
2
$ echo 2015-12-3,2014-12-1 | ./longago.sh
367
$ echo 2015-12-3,2013-12-3 | ./longago.sh
730
$ 
\$\endgroup\$
4
\$\begingroup\$

Julia, 67 bytes

print(Int(-diff(map(i->Date(i,"y-m-d"),split(readline(),",")))[1]))

Ungolfed:

# Read a line from STDIN
r = readline()

# Split it into two character dates
s = split(r, ",")

# Convert each to a Date object
d = map(i -> Date(i, "y-m-d"), s)

# Compute the difference in dates (first-second)
f = diff(d)[1]

# Convert the Base.Date.Day object to an integer
# Negate to get second-first
i = Int(-f)

# Print to STDOUT
print(i)
\$\endgroup\$
2
  • \$\begingroup\$ Instead of -diff(d)[1] you can use -(d...) to save a couple of bytes. What Julia version are you using by the way? On 1.2, I had to explicitly import Dates and I also can't just convert days to integers like this. \$\endgroup\$ Aug 21, 2019 at 10:49
  • \$\begingroup\$ This answer was posted in 2015, so it was probably Julia 0.3 or 0.4 at the latest. \$\endgroup\$
    – Alex A.
    Oct 4, 2019 at 0:26
4
\$\begingroup\$

Scala, 166 139 120 116 92 bytes

print(args(0).replace('-','/').split(",").map(java.util.Date.parse(_)/86400000).reduce(_-_))

Usage: scala [source filename].scala [date1],[date2]

Note: The third version (120 bytes) and on uses a deprecated API. It still compiles and works fine. Note2: Thanks to the commenters below for the great advice!

\$\endgroup\$
3
  • \$\begingroup\$ Since the trailing new line is optional you could use print instead of println. \$\endgroup\$
    – Marth
    Dec 8, 2015 at 11:55
  • \$\begingroup\$ You can remove the Object A extends App{...} part and save it as a.scala and run it with scala a.scala 2015-12-3,2015-12-1 ;) \$\endgroup\$
    – Martijn
    Dec 8, 2015 at 15:12
  • \$\begingroup\$ @MartijnR Genius! Thanks!! \$\endgroup\$
    – Ruslan
    Dec 8, 2015 at 23:51
3
\$\begingroup\$

Ruby, 69 66 65 57 55 bytes

a=->l{Time.gm *$F[l,3]};p (a[0]-a[3]).div 86400

47 bytes + 8 bytes for command line option. Thanks to Dane Anderson, saved 2 bytes.

57 bytes

p (Time.gm(*$F[0,3])-Time.gm(*$F[3,3])).div 86400

49 bytes code + 8 bytes for command line option. Saved 8 bytes with manatwork's suggestion.

65 bytes

a,b=gets.split(?,).map{|i|Time.gm *i.split(?-)};p (a-b).div 86400

66 bytes

a,b=gets.split(?,).map{|i|Time.new *i.split(?-)};p (a-b).div 86400

69 bytes

a,b=gets.split(',').map{|i|Time.new *i.split('-')};p (a-b).to_i/86400

Test it online

Ungolfed

a = -> l {
  Time.gm *$F[l,3]       # Anonymous method to parse time
}
p (a[0]-a[3]).div 86400  # Subtracts two times and divides by 24*60*60

Usage:

ruby -naF[,-] -e 'a=->l{Time.gm *$F[l,3]};p (a[0]-a[3]).div 86400' <<< '2015-12-3,2013-12-3'

=> 730
\$\endgroup\$
7
  • \$\begingroup\$ Three little chars: ','?,, '-'?-, to_i/div . \$\endgroup\$
    – manatwork
    Dec 8, 2015 at 9:59
  • \$\begingroup\$ Using some command line options may reduce it more: ruby -naF[,-] -e 'p (Time.new(*$F[0,3])-Time.new(*$F[3,3])).div 86400' <<< '2015-10-11,2015-07-11' is 59 characters as I count it. \$\endgroup\$
    – manatwork
    Dec 8, 2015 at 10:17
  • \$\begingroup\$ @manatwork Not sure if that is allowed. \$\endgroup\$
    – Vasu Adari
    Dec 8, 2015 at 11:11
  • \$\begingroup\$ The rule is that the minimum necessity needed to pass the code (in case of Ruby -e) is free, everything else has to be included in the count. There are different opinions on what exactly is that everything else. For example some members include the option separator space character and quotes around parameter values. In my view should only be counted what actually gets passed to the interpreter, extra characters required by shell syntax not. But can't remember any voice raised to disallow the use of options. \$\endgroup\$
    – manatwork
    Dec 8, 2015 at 11:24
  • 2
    \$\begingroup\$ almost not worth mentioning, but you can shave a byte by moving the repeated code into a proc: t=->l{Time.gm(*$F[l,3])};p (t[0]-t[3]).div 86400 \$\endgroup\$ Dec 8, 2015 at 17:52
2
\$\begingroup\$

Japt, 41 bytes

A=K$.parse)(($B=Uq',  g0)-$A($Bg1))/864e5

So far this is the best I can get it as all the variables and $ and parenthesis really kill the byte count.

Try it online

Explanation

             // Implicit: U is set to input
A=K$.parse)  // Set variable A to date parsing function
(($B=Uq',    // Set B to input split by ,
  g0)        // Get the first date and parse
-            // Subtract...
$A(          // Parse this date...
   $Bg1      // Get's second date
))/864e5     // Divides by 86,400,000
\$\endgroup\$
2
\$\begingroup\$

MATLAB, 41 31 bytes

disp(-diff(datenum(input(''))))
{'2015-12-03', '2014-12-22'}
   346  

Input must be a comma-separated cell array. datenum converts the input cell into a 2x1 numeric array with the time stamp. diff takes the difference between the two.


Old solution, 41 bytes:

disp(-diff(datenum(strsplit(input('')))))

Input must be a comma-separated string:

disp(-diff(datenum(strsplit(input('')))))
'2015-12-03, 2014-12-22'
   346

The curious ways of programming. This works because of MATLAB's implicit casting between datatypes.

The output from strsplit(input('')) is a cell of strings. You cannot use diff on a cell, but fortunately, datenum works, and it actually casts the cell input back to a 2x1 numeric array, making diff possible to use.

You can specify a whole lot of delimiters in strsplit, but comma is the default one. Also, the default input to datenum is on the format yyyy-mm-dd. For those reasons, a lot of specifications such as: datenum(s,'yyyy-mm-dd') are avoided, saving a whole lot of bytes.

For the record, this would be 21 bytes if I could use a function:

@(s)-diff(datenum(s))
\$\endgroup\$
2
  • 1
    \$\begingroup\$ How could I forget about diff... Might as well just delete my submission, because it's essentially the same, but with 2 calls to datenum instead. \$\endgroup\$
    – slvrbld
    Dec 8, 2015 at 9:15
  • 1
    \$\begingroup\$ Great choice of input format! \$\endgroup\$
    – Luis Mendo
    Dec 9, 2015 at 13:09
2
\$\begingroup\$

Javascript ES6, 63 bytes

Tested in chrome.

alert(((p=Date.parse)((a=prompt().split`,`)[0])-p(a[1]))/864e5)
\$\endgroup\$
12
  • \$\begingroup\$ comma-seperated from the question \$\endgroup\$
    – user46167
    Dec 8, 2015 at 2:22
  • \$\begingroup\$ @ev3commander Yes, I just fixed that. \$\endgroup\$ Dec 8, 2015 at 2:22
  • 2
    \$\begingroup\$ @SuperJedi224 Huh. Firefox gives Invalid date, whilst chrome happily proceeds. \$\endgroup\$ Dec 8, 2015 at 3:45
  • 5
    \$\begingroup\$ I'd mark this Chrome-specific as it only seems to work in chrome. I think the compliant way would be to use Date.parse and replace the - with / \$\endgroup\$
    – Downgoat
    Dec 8, 2015 at 3:58
  • 1
    \$\begingroup\$ Most browsers require the date to be padded so 2015-12-03 will work but 2015-12-3 will not (except in Chrome). The question does say that the date will be in the format YYYY-MM-DD so if the input really did follow that it would be cross-browser compatible, however the examples seem to say otherwise. Anyway, you could use Date.parse instead of new Date to save 2 bytes: alert((p((a=prompt(p=Date.parse).split`,`)[0])-p(a[1]))/864e5) \$\endgroup\$
    – user81655
    Dec 8, 2015 at 4:32
2
\$\begingroup\$

PHP, 63 64 77 bytes

Found that the classic approach is shorter than the OOP one:

$x=fgetcsv(STDIN);$s=strtotime;echo($s($x[0])-$s($x[1]))/86400;

Reads the comma separated string from STDIN.


The straight forward OOP way (77 bytes):

$x=fgetcsv(STDIN);echo(new DateTime($x[0]))->diff(new DateTime($x[1]))->days;

Edits

  • Saved 13 bytes by using strtotime instead of DateTime.
  • Saved 1 byte by storing strtotime in a variable. Thanks to Blackhole.
\$\endgroup\$
1
  • \$\begingroup\$ -3 bytes: move the assignments to their first usage in parentheses (-1 byte each) and You can use <?= instead of echo. \$\endgroup\$
    – Titus
    Dec 21, 2016 at 16:33
2
\$\begingroup\$

Excel, 25 bytes

=LEFT(A1,10)-RIGHT(A1,10)

Excel automatically handles the strings as dates.

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

TeaScript, 24 bytes

((a=D.parse)×-a(y©/864e5

Uses Date.parse to parse the date, then get's the difference and divides.

Try it online

Explanation && Ungolfed

((a=D.parse)(x)-a(y))/864e5

               // Implicit: x is first date
               // y is second date
(
 (a=D.parse)   // Assign Date.parse to 'a'
 (x)           // Run Date.parse with first date
 -a(y)         // Subtract Date.parse run with second date
)/864e5        // Divide by 86,400,000
\$\endgroup\$
1
\$\begingroup\$

VBA, 69 bytes

Function x(s)
g=Split(s, ",")
x=CDate(g(0))-CDate(g(1))
End Function
\$\endgroup\$
1
\$\begingroup\$

psql, 75 bytes

(74 characters code + 1 character command line option)

\prompt i
select split_part(:'i',',',1)::date-split_part(:'i',',',2)::date

psql is PostgreSQL's interactive terminal. To respect the “Each submission must be a full program.” rule, the code reads the input itself.

Sample run:

bash-4.3$ psql -tf how-long-was-this.sql <<< '2015-12-3,2013-12-3'
      730
\$\endgroup\$
1
\$\begingroup\$

Python 2, 109 113 bytes

import datetime as d 
j=[d.date(*[int(k) for k in g.split('-')]) for g in raw_input().split(',')]
print j[0]-j[1]
\$\endgroup\$
1
  • \$\begingroup\$ The spaces between )s and fors are not needed. \$\endgroup\$
    – Wheat Wizard
    Jun 17, 2020 at 14:09
1
\$\begingroup\$

MATL, 5 bytes

iPYOd

This is the same as StewieGriffin's answer, except I used flip then diff rather than diff then negating the result.

Full explanation, with corresponding Matlab functions:

i   %// input(''), get input
P   %// flip, flips the array
YO  %// datenum, converts date string into an integer
d   %// diff, finds the difference between dates
\$\endgroup\$
11
  • 2
    \$\begingroup\$ Note: Whilst MATL was only released on December 12, after this challenge was posted, I came up with this answer on December 9 using a pre-release MATL compiler, which is almost identical to the released compiler, this code is the same. \$\endgroup\$
    – David
    Dec 13, 2015 at 23:54
  • 2
    \$\begingroup\$ Also, this is in no way an endorsement of the popular Apple portable music device :P \$\endgroup\$
    – David
    Dec 13, 2015 at 23:54
  • 1
    \$\begingroup\$ I should have used o for the datenum function :-D \$\endgroup\$
    – Luis Mendo
    Dec 13, 2015 at 23:55
  • \$\begingroup\$ That would have been amazing! \$\endgroup\$
    – David
    Dec 13, 2015 at 23:55
  • 1
    \$\begingroup\$ @ev3commander most answers on PPCG are the same as other answers, especially in cases like this where 4 commands suffice. \$\endgroup\$
    – David
    Dec 14, 2015 at 21:32
1
\$\begingroup\$

PowerShell v2+, 50 44 Bytes

$a,$b=$args-split','|%{date $_};($a-$b).Days

Takes input argument as a string, splits it on the comma, then pipes the array via a built-in alias date short for Get-Date to convert our strings into .NET datetime format. Those two dates then get stored simultaneously into $a and $b. We then use an overloaded-subtraction-operator to subtract the second from the first, and output the .Days thereof.

Golfed 6 bytes thanks to TessellatingHeckler.

Technically non-competing, as it doesn't have an online interpreter available, since the FOSS implementation of PowerShell, Pash, is around PowerShell v0.5. It doesn't support -split yet, let alone the complex .NET date functionality.

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

Japt, 13 bytes

£ÐXÃr- zHÑ7e5

Try it

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

JavaScript, 58 53 bytes thanks to @targumon!

n=>(new Date((a=n.split`,`)[0])-new Date(a[1]))/864e5

Older version:

n=>(new Date((a=n.split(','))[0])-new Date(a[1]))/86400000

My submissions seem to have a reputation of being boring.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Let's push it down to 53 bytes: n=>(new Date((a=n.split`,`)[0])-new Date(a[1]))/864e5 \$\endgroup\$
    – targumon
    Mar 11, 2021 at 14:16
0
\$\begingroup\$

Jolf, 33 bytes

Only works in Chrome. Noncompeting, since language updates postdate question. I'll add a more thorough explanation later.

$S=$viGi', mDN~DH r}/m4SmeP"864"5

“Explanation”

$S=$viGi', mDN~DH r}
$S=$                 sets S equal to
    viGi',           take string input and reassign it to the comma-split input
           mD      } map with this function 
             N~DH r  return the time of the date of H (element)

/m4SmeP"864"5
/             divide
 m4S           subtraction applied to S (S[0] - S[1])
    meP"864"5  and 864 * 10 ^ 5 (thanks to Super Jedi for his nice constant)
              implicit output
\$\endgroup\$
1
  • \$\begingroup\$ How about you put "noncompeting" in your header? \$\endgroup\$
    – user46167
    Dec 24, 2015 at 13:29
0
\$\begingroup\$

MATLAB, 59 bytes

s=strsplit(input(''),',');disp(datenum(s{1})-datenum(s{2}))

Very straightforward approach: input has to be given as a string from the command window. The input string is then split and the number of days between the dates (and nothing else) is calculated from the serial date numbers. I'm quite sure there is a way to avoid the need for calling datenum twice though...

\$\endgroup\$
0
\$\begingroup\$

T-SQL + SQLCMD, 51 bytes

PRINT DATEDIFF(D,RIGHT('$(i)',10),LEFT('$(i)',10))

Tested with SQL Server 2008R2. The $(i) is replaced with the input provided as a command line argument.

Sample run:

sqlcmd -i script.sql -v i="2015-12-08,2016-01-01"
-24
\$\endgroup\$
0
\$\begingroup\$

Mathematica, 61 bytes

Print@First[#-#2&@@DateObject/@InputString[]~StringSplit~","]

Basic date subtraction.

\$\endgroup\$
0
\$\begingroup\$

Perl, 91 86 + 2 for np flags, 88 bytes

use Date::Calc qw(Delta_Days);($a,$b)=split(/,/);$_=Delta_Days(split(/-/,$b),split(/-/,$a))

use Date::Parse;$_=str2time((split(/,/,$_))[0])-str2time((split(/,/,$_))[1]);$_/=86400

Example

$ echo 2015-12-3,2015-12-1 | perl -npe 'use Date::Parse;$_=str2time((split(/,/,$_))[0])-str2time((split(/,/,$_))[1]);$_/=86400'
2
\$\endgroup\$
0
\$\begingroup\$

jq, 50 bytes

(49 characters code + 1 character command line option)

./","|map(.+"T0:0:0Z"|fromdate)|(.[0]-.[1])/86400

Sample run:

bash-4.3$ ~/bin/jq -R './","|map(.+"T0:0:0Z"|fromdate)|(.[0]-.[1])/86400' <<< '2015-12-3,2013-12-3'
730

On-line test (Passing -R through URL is not supported – so input passed as string "2015-12-3,2013-12-3".)

\$\endgroup\$
0
\$\begingroup\$

Mathematica, 56 bytes

Print@#&@@-DateDifference@@InputString[]~StringSplit~","

Most (all?) date functions will try to parse string inputs into dates automatically.

\$\endgroup\$
0
\$\begingroup\$

C# .NET, 148 bytes

using System;class P{static void Main(string[]a){Console.Write((DateTime.Parse(a[0].Substring(11,10))-DateTime.Parse(a[0].Substring(0,10))).Days);}}

Try Online

\$\endgroup\$
0
\$\begingroup\$

C (gcc), 225 199 bytes

-25 bytes thanks to ceilingcat! Replacing an array of numbers with a string of wide-characters is some proper black-magic

-1 byte by adding an additional character to the start of the string, allowing for indexing with [m] instead of [m-1]

a,b,d,e,f;i(m,y){return(a=y-1)*365+a/4-a/100+a/400+L"\0\37;Zx\x97µÔóđİŎ"[m]+(m>1&(y%100*!(y%4)||y%400<1));}main(c){scanf("%d-%d-%d,%d-%d-%d",&a,&b,&c,&d,&e,&f);printf("%d",i(b,a)-i(e,d)+c-f);}

Try it online!

Perhaps the code could be shortened by using <time.h>, but not using it makes for a fun challenge. The difference between dates is calculated using a golfed version of this code.

Un-golfed:

a,b,d,e,f;
i(m,y){
    return(a=y-1)*365 /*Num days in y-1 years*/
        +a/4-a/100+a/400 /*Add previous years' leap days*/
        +L" \0\37;Zx\x97µÔóđİŎ"[m] /*Add days this year until month*/
        +(m>1&(y%100*!(y%4)||y%400<1)); /*Add this year's leap day*/
}
main(c){
    scanf("%d-%d-%d,%d-%d-%d",&a,&b,&c,&d,&e,&f);
    printf("%d",i(b,a)-i(e,d)+c-f);
}
\$\endgroup\$
0

Your Answer

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