Days between dates: Difference between revisions

(Added Fōrmulæ solution)
Line 988:
{{out}}
<pre>Number of days between 2019-01-01 and 2019-10-19: 291</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
Two solutions are provided: the first uses jq's built-ins and is very brief.
The second starts from first principles,
and is of potential interest because of the various generic functions
that are provided. The output is the same in both cases.
 
===Using jq's built-ins===
<lang jq>
def days_between(yyyymmddBefore; yyyymmddAfter):
(yyyymmddBefore | strptime("%Y-%m-%d") | mktime) as $before
| (yyyymmddAfter | strptime("%Y-%m-%d") | mktime) as $after
# leap seconds are always inserted
| (($after - $before) / (24*60*60) | floor) ;
 
def task:
def prolog: "In the following, if the dates are not the same,",
"the \"from\" date is included in the count of days, but the \"to\" date is not.\n",
"If the first date is later than the second date, the count of days is negated.";
 
def dates:
["1995-11-21", "1995-11-21"],
["2019-01-01", "2019-01-02"],
["2019-01-02", "2019-01-01"],
["2019-01-01", "2019-03-01"],
["2020-01-01", "2020-03-01"],
["1902-01-01", "1968-12-25"],
["2090-01-01", "2098-12-25"],
["1902-01-01", "2098-12-25"],
["1970-01-01", "2019-10-18"],
["2019-03-29", "2029-03-29"],
["2020-02-29", "2020-03-01"] ;
 
prolog,
(dates | "The number of days from \(.[0]) until \(.[1]) is \(days_between(.[0]; .[1] ))")
;
 
task
</lang>
{{out}}
<pre>
In the following, if the dates are not the same,
the "from" date is included in the count of days, but the "to" date is not.
 
If the first date is later than the second date, the count of days is negated.
The number of days from 1995-11-21 until 1995-11-21 is 0
The number of days from 2019-01-01 until 2019-01-02 is 1
The number of days from 2019-01-02 until 2019-01-01 is -1
The number of days from 2019-01-01 until 2019-03-01 is 59
The number of days from 2020-01-01 until 2020-03-01 is 60
The number of days from 1902-01-01 until 1968-12-25 is 24465
The number of days from 2090-01-01 until 2098-12-25 is 3280
The number of days from 1902-01-01 until 2098-12-25 is 71947
The number of days from 1970-01-01 until 2019-10-18 is 18187
The number of days from 2019-03-29 until 2029-03-29 is 3653
The number of days from 2020-02-29 until 2020-03-01 is 1
</pre>
 
===From first principles===
'''Adapted from [[#Wren|Wren]]'''
<lang jq>
# In general, dates should be valid Julian dates on or after Jan 1, 0001, but
# for the most part, this is not checked, in part because some
# computations based on ostensibly invalid dates do produce useful
# results, e.g. days(2000; 1; 1) computes the number of days from Jan 1, 0001
# up to and including Jan 1, 2000 whereas days(2000; 1; 0) excludes Jan 1, 2000.
 
# Output: the number of days from and including Jan 1, 0001,
# up to but excluding Jan 1 in the year $y for $y >= 1
def days_before:
if . < 1
then "The input to days_before should be a positive integer, not \(.)"|error
else (. - 1 | floor) as $y
| $y*365 + (($y/4)|floor) - (($y/100)|floor) + (($y/400)|floor)
end;
 
def isLeapYear:
.%4 == 0 and (.%100 != 0 or .%400 == 0);
 
# The day of the year (Jan 1 is 1)
def day_of_year($y; $m; $d):
def diy: [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
def diy2: [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366];
$d + if ($y|isLeapYear) then diy2[$m-1] else diy[$m-1] end;
 
# Output: the number of days from Jan 1, 0001 to the specified date, inclusive.
def days($y; $m; $d):
($y | days_before) + day_of_year($y; $m; $d);
 
# Output: the signed difference in the "days" values of the two dates.
# If the first specified date is later than the second specified date,
# then the result is the number of days from and including the earlier date,
# up to but excluding the later date.
def days_between(Year; Month; Day; laterYear; laterMonth; laterDay):
days(laterYear; laterMonth; laterDay) -
days(Year; Month; Day);
 
# Dates in yyyy-mm-dd format or as a numeric array [y,m,d]
def days_between(date; later):
def toa: if type == "string" then split("-") | map(tonumber) else . end;
(later | toa) as $later
| (date | toa) as $date
| days_between($date[0]; $date[1]; $date[2]; $later[0]; $later[1]; $later[2]);
</lang>
'''The Tasks'''
 
As above.
{{out}}
Same as above.
 
 
=={{header|Julia}}==
2,458

edits