Days between dates
- 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 dateToIntsToo(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] = [ daysbetween:dateToInts(DateOne,X) || X <- L], [Y2,M2,D2] = [ daysbetween: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 formatting kernel math ;
- days-between ( ymd-str ymd-str -- n )
[ ymd>timestamp ] bi@ time- duration>days abs ;
"2019-01-01" "2019-09-30" "2016-01-01" "2016-09-30" ! leap year [
[ days-between ] 2keep "There are %d days between %s and %s\n" printf
] 2bi@</lang>
- Output:
There are 272 days between 2019-01-01 and 2019-09-30 There are 273 days between 2016-01-01 and 2016-09-30
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
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>
- !/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