Days between dates: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|REXX}}: added the REXX computer programming language for this task.)
m (→‎{{header|REXX}}: FWIW ISO:8801 doesn't exist)
Line 218: Line 218:
Programming note:   the   '''B'''   ('''B'''ase)   an option for the   '''date'''   BIF which indicates to compute the number of
Programming note:   the   '''B'''   ('''B'''ase)   an option for the   '''date'''   BIF which indicates to compute the number of
<br>days since the beginning of the Gregorian calendar, &nbsp; and &nbsp; '''I''' &nbsp; which is the option that indicates the date is in
<br>days since the beginning of the Gregorian calendar, &nbsp; and &nbsp; '''I''' &nbsp; which is the option that indicates the date is in
<br>the &nbsp; '''ISO''' &nbsp; (International Standards Organization standard 8801:2004) &nbsp; format.
<br>the &nbsp; '''ISO''' &nbsp; (International Standards Organization standard 8601:2004) &nbsp; format.
<lang rexx>/*REXX program computes the number of days between two dates in the form of YYYY-MM-DD */
<lang rexx>/*REXX program computes the number of days between two dates in the form of YYYY-MM-DD */
parse arg $1 $2 . /*get 2 arguments (dates) from the C.L.*/
parse arg $1 $2 . /*get 2 arguments (dates) from the C.L.*/

Revision as of 21:15, 2 October 2019

Days between dates is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Calculate the number of days between two dates. Date input should be of the form YYYY-MM-DD.

Motivation

To demonstrate one of the numerous ways this can be done.


Erlang

<lang erlang>

-module(daysbetween). -export([between/2,dateToInts/2]).

% Return Year or Month or Date from datestring dateToInts(String, POS) ->

 list_to_integer( lists:nth( POS, string:tokens(String, "-") ) ).

% Alternative form of above % dateToInts(String,POS) -> % list_to_integer( lists:nth( POS, re:split(String ,"-", [{return,list},trim]) ) ).

% Return the number of days between dates formatted "2019-09-30" between(DateOne,DateTwo) ->

 L = [1,2,3],
 [Y1,M1,D1] =  [ dateToInts(DateOne,X) || X <- L],
 [Y2,M2,D2] =  [ dateToInts(DateTwo,X) || X <- L],
 GregOne = calendar:date_to_gregorian_days(Y1,M1,D1),
 GregTwo = calendar:date_to_gregorian_days(Y2,M2,D2),
 GregTwo - GregOne.
     

</lang>

Output:

erlang shell:

30> c(daysbetween).
c(daysbetween).
{ok,daysbetween}
31> daysbetween:between("2019-01-01", "2019-09-30").
daysbetween:between("2019-01-01", "2019-09-30").
272

Factor

Factor supports the addition and subtraction of timestamps and durations with the time+ and time- words. <lang factor>USING: calendar calendar.parser kernel math prettyprint ;

days-between ( ymd-str ymd-str -- n )
   [ ymd>timestamp ] bi@ time- duration>days abs ;

"2019-01-01" "2019-09-30" days-between . "2016-01-01" "2016-09-30" days-between .  ! leap year</lang>

Output:
272
273

Go

<lang go>package main

import (

   "fmt"
   "log"
   "time"

)

const layout = "2006-01-02" // template for time.Parse

// Parameters assumed to be in YYYY-MM-DD format. func daysBetween(date1, date2 string) int {

   t1, err := time.Parse(layout, date1)
   check(err)
   t2, err := time.Parse(layout, date2)
   check(err)
   days := int(t1.Sub(t2).Hours() / 24)
   if days < 0 {
       days = -days
   }
   return days

}

func check(err error) {

   if err != nil {
       log.Fatal(err)
   }

}

func main() {

   date1, date2 := "2019-01-01", "2019-09-30"
   days := daysBetween(date1, date2)
   fmt.Printf("There are %d days between %s and %s\n", days, date1, date2)
   date1, date2 = "2015-12-31", "2016-09-30"
   days = daysBetween(date1, date2)
   fmt.Printf("There are %d days between %s and %s\n", days, date1, date2)

}</lang>

Output:
There are 272 days between 2019-01-01 and 2019-09-30
There are 274 days between 2015-12-31 and 2016-09-30

Lua

This uses os.difftime to compare two Epoch times. Not to be used with dates before 1970. <lang lua>SECONDS_IN_A_DAY = 60 * 60 * 24

-- Convert date string as YYYY-MM-DD to Epoch time. function parseDate (str)

 local y, m, d = string.match(str, "(%d+)-(%d+)-(%d+)")
 return os.time({year = y, month = m, day = d})

end

-- Main procedure io.write("Enter date 1: ") local d1 = parseDate(io.read()) io.write("Enter date 2: ") local d2 = parseDate(io.read()) local diff = math.ceil(os.difftime(d2, d1) / SECONDS_IN_A_DAY) print("There are " .. diff .. " days between these dates.")</lang>

Output:
Enter date 1: 1970-01-01
Enter date 2: 2019-10-02
There are 18171 days between these dates.

Perl

Would not reinvent this wheel. <lang perl>use feature 'say'; use Date::Calc qw(Delta_Days);

say Delta_Days(2018,7,13, 2019,9,13); # triskaidekaphobia say Delta_Days(1900,1,1, 2000,1,1); # a century say Delta_Days(2000,1,1, 2100,1,1); # another, with one extra leap day say Delta_Days(2020,1,1, 2019,10,1); # backwards in time say Delta_Days(2019,2,29, 2019,3,1); # croaks</lang>

Output:
427
36524
36525
-92
Date::Calc::PP::Delta_Days(): Date::Calc::Delta_Days(): not a valid date at Days_between_dates line 10

Perl 6

Dates are first class objects in Perl 6 and may have arithmetic in days done directly on them. <lang perl6>say Date.new('2019-09-30') - Date.new('2019-01-01');

say Date.new('2019-03-01') - Date.new('2019-02-01');

say Date.new('2020-03-01') - Date.new('2020-02-01');

say Date.new('2029-03-29') - Date.new('2019-03-29');

say Date.new('2019-01-01') + 90;

say Date.new('2020-01-01') + 90;

say Date.new('2019-02-29') + 30;

CATCH { default { .message.say; exit; } };</lang>

272
28
29
3653
2019-04-01
2020-03-31
Day out of range. Is: 29, should be in 1..28

Python

<lang python>

  1. !/usr/bin/python

import sys

Difference between two dates = g(y2,m2,d2) - g(y1,m1,d1)

   Where g() gives us the Gregorian Calendar Day
   Inspired  by discussion at:
   https://stackoverflow.com/questions/12862226/the-implementation-of-calculating-the-number-of-days-between-2-dates

def days( y,m,d ):

  input year and month are shifted to begin the year in march
 m = (m + 9) % 12 
 y = y - m/10
  with (m*306 + 5)/10 the number of days from march 1 to the current 'm' month 
 result = 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
 return result

def diff(one,two):

 [y1,m1,d1] = one.split('-')
 [y2,m2,d2] = two.split('-')
 # strings to integers
 year2 = days( int(y2),int(m2),int(d2))
 year1 = days( int(y1), int(m1), int(d1) )
 return year2 - year1

if __name__ == "__main__":

 one = sys.argv[1]
 two = sys.argv[2]
 print diff(one,two)

</lang>

Output:
python days-between.py 2019-01-01 2019-09-30
272

REXX

Works with: Regina REXX


Programming note:   the   B   (Base)   an option for the   date   BIF which indicates to compute the number of
days since the beginning of the Gregorian calendar,   and   I   which is the option that indicates the date is in
the   ISO   (International Standards Organization standard 8601:2004)   format. <lang rexx>/*REXX program computes the number of days between two dates in the form of YYYY-MM-DD */ parse arg $1 $2 . /*get 2 arguments (dates) from the C.L.*/ say abs( date('B',$1,"I") - date('B',$2,"I") ) ' days between ' $1 " and " $2

                                                /*stick a fork in it,  we're all done. */</lang>
output   when using the inputs of:     2020-10-02   2000-01-01
7580  days between  2020-10-02  and  2000-01-01

zkl

<lang zkl>var [const] TD=Time.Date; today:=TD.parseDate("--"); // "yyyy-mm-dd" and variations --> (y,m,d) // or Time.Clock.UTC --> (y,m,d,h,m,s) then:=TD.parseDate("2018-9-30"); diff:=TD.deltaDays(then,today.xplode()); // ( (y,m,d), y,m,d ) println("Number of days between %s and %s: %d".fmt(then,today,diff)); println("Number of days between %s and %s: %d".fmt(

  TD.toYMDString(today.xplode()),	// to(y,m,d) not to((y,m,d))
  TD.toYMDString(then.xplode()),
  TD.deltaDays(today,then.xplode())));</lang>
Output:
Number of days between L(2018,9,30) and L(2019,9,30): 365
Number of days between 2019-09-30 and 2018-09-30: -365