Étude 6-3: Accumulating the Sum of a List

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).

See a suggested solution in Appendix A.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.137.93