Add a function julian/1
to the dates
module that you wrote in
Étude 5-2. Given a string in ISO format ("yyyy-mm-dd"
), it
returns the Julian date: the day of the year.
Here is some sample output.
1>
c
(
dates
).
{ok,dates}
2>
dates
:
julian
(
"2012-12-31"
).
366
3>
dates
:
julian
(
"2013-12-31"
).
365
4>
dates
:
julian
(
"2012-02-05"
).
36
5>
dates
:
julian
(
"2013-02-05"
).
36
6>
dates
:
julian
(
"1900-03-01"
).
60
7>
dates
:
julian
(
"2000-03-01"
).
61
126>
dates
:
julian
(
"2013-01-01"
).
1
The julian/1
function defines a 12-item list called DaysPerMonth
that
contains the number of days in each month, splits the date into
the year, month, and day (using the date_parts/1
function you wrote in
Étude 5-2, and then calls helper function julian/5
(yes, 5).
The julian/5
function does all of the work. Its arguments are the year,
month, day, the list of days per month, and an accumulated total, which
starts at zero. julian/5
takes the head of the days per month list and
adds it to the accumulator, and then calls julian/5
again with the
tail of the days per month list and the accumulator value as its last two
arguments.
Let’s take, as an example, the sequence of calls for April 18, 2013:
julian(2013, 4, 18, [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 0). julian(2013, 4, 18, [28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 31). julian(2013, 4, 18, [31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 59). julian(2013, 4, 18, [30, 31, 30, 31, 31, 30, 31, 30, 31], 90).
At this point, the accumulator has all the days up through the beginning of
April, so the last call to julian/5
just adds the 18 remaining days
and yields 108 as its result.
You know you are doing the last call when you have “used up”
the first month-1 items in
the list of days per month. That happens when
the month number is greater
than (13 - length(
.days_per_month_list
))
Of course, there’s still the problem of leap years. For non-leap years,
the last call to julian/5
adds the number of days in the target month.
For leap years, the function must add the number of days in the
target month plus one—but only if the month is after February.
I’ll give you the code for the is_leap_year/1
function for free; it returns
true
if the given year is a leap year, false
otherwise.
is_leap_year
(
Year
)
->
(
Year
rem
4
==
0
andalso
Year
rem
100
/=
0
)
orelse
(
Year
rem
400
==
0
).
18.218.137.93