Monthly Archives: April 2015

Erlang Thursday – calendar:is_leap_year/1

Today’s Erlang Thursday is on calendar:is_leap_year/1.

calendar:is_leap_year/1 takes a non-negative integer value representing a year, and will return true if that year is a leap year, or false otherwise.

calendar:is_leap_year(2015).
% false
calendar:is_leap_year(2012).
% true
calendar:is_leap_year(2017).
% false
calendar:is_leap_year(2000).
% true
calendar:is_leap_year(1900).
% false
calendar:is_leap_year(0).
% true

By having a built in function as part of the core Erlang libraries, it means you don’t have to code up the rules, or even go lookup the rules to remember how the century years are determined to be leap years or not.

And if you do pass in a negative number for the year, Erlang will raise an exception, as there are no clauses which match a negative number for the year.

calendar:is_leap_year(-1).
% ** exception error: no function clause matching calendar:is_leap_year(-1) (calendar.erl, line 183)
calendar:is_leap_year(-4).
% ** exception error: no function clause matching calendar:is_leap_year(-4) (calendar.erl, line 183)

–Proctor

Ruby Tuesday – Date#leap?

Today’s Ruby Tuesday is on Date#leap?.

Date#leap? operates on a Date object, and returns true if the year is a leap year in the Gregorian calender, or false if not.

Date.new(2015, 1, 4).leap?
=> false
Date.new(2012, 1, 1).leap?
# => true
Date.new(2017, 1, 1).leap?
# => false
Date.new(2000, 1, 1).leap?
# => true
Date.new(1900, 1, 1).leap?
# => false

By using Date#leap?, you don’t have to code the rules to check if a year is a leap year, or even have to double check the rules about when the century is a leap year.

There is also a class level version Date::leap?, that will take a integer value for the year, and return a true or false value.

Date.leap? 2015
# => false
Date.leap? 2012
# => true
Date.leap? 2017
# => false
Date.leap? 2000
# => true
Date.leap? 1900
# => false

Both the instance and class level versions of ‘leap?` can handle Year Zero, and negative years.

Date.leap? -1
# => false
Date.leap? -4
# => true
Date.leap? 0
# => true
Date.new(-4, 1, 1).leap?
# => true

I wouldn’t know if that is valid myself, but that is why it is useful to have this a built in method on Date instead of having to code it up myself.

–Proctor

Erlang Thursday – calendar:valid_date/3

Today’s Erlang Thursday is calendar:valid_date/3.

Originally, I was thinking it was going to be calendar:time_difference/3, but then I looked into the Erlang documentation for the calendar module. and saw that it was marked as obsolete, so today I present calendar:valid_date/3.

The arguments to calendar:valid_date/3 are an integer for the year, integer for the month, and an integer for the day. calendar:valid_date/3 returns the atom true if the day passed in is a valid date, and the atom false if it is not a valid date.

calendar:valid_date(2015, 04, 31).
% false
calendar:valid_date(2015, 04, 30).
% true
calendar:valid_date(2015, 02, 29).
% false
calendar:valid_date(2012, 02, 29).
% true
calendar:valid_date(2015, 11, 31).
% false
calendar:valid_date(2015, 11, 76).
% false
calendar:valid_date(2015, 17, 13).
% false

Just a quick check for our sanity that the day this post was published is a valid date as well.

calendar:valid_date(2015, 04, 23).
% true

Now let’s try to break this a bit and test to see how it can handle 0‘s and negative integer values.

calendar:valid_date(-1, 04, 23).
% false
calendar:valid_date(2015, -7, 21).
% false
calendar:valid_date(2015, 7, -13).
% false
calendar:valid_date(0, 0, 0).
% false

As one might hope, unless you deal with B.C. era dates often, a date with a negative value is not a valid date.

Erlang also provides a calendar:valid_date/1 that takes a tuple of the year, month, and day values as well.

calendar:valid_date({2015, 11, 76}).
% false
calendar:valid_date({2015, 04, 23}).
% true

–Proctor

Ruby Tuesday – Date#-

Today’s Ruby Tuesday is on Date#-.

Date#- returns the difference between two dates if passed a Date object. The difference is expressed as a rational number, as this method is also available on DateTime objects as well.

Date.new(2015, 4, 21) - Date.new(1999, 12, 31)
# => (5590/1)
Date.new(2015, 4, 21) - Date.new(1999, 4, 20)
# => (5845/1)
Date.new(2015, 4, 21) - Date.new(2015, 4, 20)
# => (1/1)
Date.new(2015, 4, 21) - Date.new(2015, 4, 23)
# => (-2/1)

If a numeric value is passed to Date#- it returns a Date object that is that many days of a difference.

Date.new(2015, 4, 21) - 1
# => #<Date: 2015-04-20 ((2457133j,0s,0n),+0s,2299161j)>
Date.new(2015, 4, 21) - 365
# => #<Date: 2014-04-21 ((2456769j,0s,0n),+0s,2299161j)>
Date.new(2015, 4, 21) - (1/2)
# => #<Date: 2015-04-21 ((2457134j,0s,0n),+0s,2299161j)>
Date.new(2015, 4, 21) - (2/2)
# => #<Date: 2015-04-20 ((2457133j,0s,0n),+0s,2299161j)>

Date#- will not only accept positive numeric values, but also negative values, and will result with a day that is in the future.

Date.new(2015, 4, 21) - -1
# => #<Date: 2015-04-22 ((2457135j,0s,0n),+0s,2299161j)>

–Proctor

Erlang Thursday – calendar:date_to_gregorian_days/3

Today’s Erlang Thursday covers calendar:date_to_gregorian_days/3.

As we saw in last week’s Erlang Thursday on calendar:day_of_the_week/3 when we were looking at some error messages, we saw that the errors were coming from calendar:date_to_gregorian_days/3.

calendar:day_of_the_week(0, 0, 0).
% ** exception error: no function clause matching calendar:date_to_gregorian_days(0,0,0) (calendar.erl, line 114)
%      in function  calendar:day_of_the_week/3 (calendar.erl, line 151)
calendar:day_of_the_week(1970, 2, 31).
% ** exception error: no true branch found when evaluating an if expression
%      in function  calendar:date_to_gregorian_days/3 (calendar.erl, line 116)
%      in call from calendar:day_of_the_week/3 (calendar.erl, line 151)
calendar:day_of_the_week(1970, 13, 2).
% ** exception error: no function clause matching calendar:last_day_of_the_month1(1970,13) (calendar.erl, line 243)
%      in function  calendar:date_to_gregorian_days/3 (calendar.erl, line 115)
%      in call from calendar:day_of_the_week/3 (calendar.erl, line 151)

I promised you at the end of that post we would take a deeper look at calendar:date_to_gregorian_days/3 next time, so let’s fulfill that promise.

calendar:date_to_gregorian_days/3 takes three arguments, a non-negative integer for the year, an integer between 1 and 12 (inclusive) for the month, and an integer between 1 and 31 (inclusive) for the day of the month, and returns the number of days since 0000-01-01 in the Gregorian calendar.

calendar:date_to_gregorian_days(2015, 4, 16).
% 736069
calendar:date_to_gregorian_days(0, 1, 1).
% 0
calendar:date_to_gregorian_days(1, 1, 1).
% 366
calendar:date_to_gregorian_days(1970, 1, 1).
% 719528
calendar:date_to_gregorian_days(1999, 12, 31).
% 730484

There is also a version calendar:date_to_gregorian_days/1, that takes a tuple of year, month, and day available if your code already has the date in tuple format.

calendar:date_to_gregorian_days({2015, 4, 16}).
% 736069
calendar:date_to_gregorian_days({0, 1, 1}).
% 0
calendar:date_to_gregorian_days({1, 1, 1}).
% 366

And if we pass something invalid to calendar:date_to_gregorian_days/1, we see that it is calling calendar:date_to_gregorian_days/3. So it is just a nice helper function that does the pattern match destructing for us.

calendar:date_to_gregorian_days({1, 1, 0}).
** exception error: no function clause matching calendar:date_to_gregorian_days(1,1,0) (calendar.erl, line 114)

–Proctor

Ruby Tuesday – Date#jd

Today’s Ruby Tuesday covers Date#jd.

Date#jd returns the number of days since the beginning of the Julian calendar.

require 'date'
# => true

Date.new.jd
# => 0
Date.new(2015, 04, 14).jd
# => 2457127
Date.new(0, 1, 1).jd
# => 1721058

If you notice above, we get 1721058 for the days since the start of the Julian calendar. One thing to notice is that we can pass an optional “Julian day number which denotes the day of calendar reform” to Date#new. If we pass in the constant Date::GREGORIAN to new, and then call Date#jd on the result, we get a different value coming back for the number of days since the start of the Julian calendar, 1721060 vs 1721058.

Date.new(0, 1, 1, Date::GREGORIAN).jd
=> 1721060

While Ruby does not have a corresponding method for getting the number of days since the start of the Gregorian calendar, we can do a difference between the number of Julian days for a date and the number of Julian days for the date 0000-01-01. But be warned, as we just saw above, to get an accurate number, we need to specify that we want 0000-01-01 to be the Gregorian version of that date.

Date.new(2015, 04, 14).jd - Date.new(0, 1, 1).jd
# => 736069
Date.new(2015, 04, 14).jd - Date.new(0, 1, 1, Date::GREGORIAN).jd
# => 736067
Date.new(2015, 04, 14, Date::GREGORIAN).jd - Date.new(0, 1, 1, Date::GREGORIAN).jd
# => 736067

If we just construct a new Date, and do not specify and Julian start date, we notice that we can see the number of Julian days in the constructor, and if we specify we want the date to be Gregorian calendar based, we can see the number of Julian days is different there as well.

Date.new(0, 1, 1)
# => #<Date: 0000-01-01 ((1721058j,0s,0n),+0s,2299161j)>
Date.new(0, 1, 1, Date::GREGORIAN)
# => #<Date: 0000-01-01 ((1721060j,0s,0n),+0s,-Infj)>

Hope this shined as little bit of knowledge on Ruby Dates for you as it did me.

–Proctor

Erlang Thursday – calendar:day_of_the_week/3

Today’s Erlang Thursday is covers calendar:day_of_the_week/3.

calendar:day_of_the_week/3 allows you to get the day of the week a day occurred on when passed a year, a month and a day.

The first argument represents the year and must be a non-negative integer. The second argument is the month and must be an integer value between 1 and 12 inclusive, representing the 12 months of the Gregorian Calendar, with January being month one. The final argument to calendar:day_of_the_week/3 is the date, and is expected to be a integer between 1 and 31 inclusive.

calendar:day_of_the_week/3 returns an integer value in between 1 and 7 inclusive, with a return value of 1 representing Monday, and a 7 being Sunday.

calendar:day_of_the_week(1, 1, 1).
% 1
calendar:day_of_the_week(1970, 1, 1).
% 4
calendar:day_of_the_week(1999, 12, 31).
% 5
calendar:day_of_the_week(0, 1, 1).
% 6

As you can see that the publish date of this Erlang Thursday post, 2015-04-09, returns a 4, which is in fact a Thursday according to Erlang.

calendar:day_of_the_week(2015, 4, 9).
% 4

There is also a calendar:day_of_the_week/1 function which has all the same constraints but instead of taking three arguments, takes one argument that is a three-tuple of the year, month, and day.

calendar:day_of_the_week({2015, 4, 9}).
% 4
calendar:day_of_the_week({1970, 1, 1}).
% 4
calendar:day_of_the_week({1999, 12, 31}).
% 5

And in the spirit of helping to recognize error messages when we see them, let’s take a look at what we get when we pass some invalid inputs to calendar:day_of_the_week/3.

calendar:day_of_the_week(0, 0, 0).
% ** exception error: no function clause matching calendar:date_to_gregorian_days(0,0,0) (calendar.erl, line 114)
%      in function  calendar:day_of_the_week/3 (calendar.erl, line 151)
calendar:day_of_the_week(1970, 2, 31).
% ** exception error: no true branch found when evaluating an if expression
%      in function  calendar:date_to_gregorian_days/3 (calendar.erl, line 116)
%      in call from calendar:day_of_the_week/3 (calendar.erl, line 151)
calendar:day_of_the_week(1970, 13, 2).
% ** exception error: no function clause matching calendar:last_day_of_the_month1(1970,13) (calendar.erl, line 243)
%      in function  calendar:date_to_gregorian_days/3 (calendar.erl, line 115)
%      in call from calendar:day_of_the_week/3 (calendar.erl, line 151)

If you look at the error messages you see that calendar:day_of_the_week/3 calls calendar:date_to_gregorian_days/3, which we will cover in next week’s Erlang Thursday.

–Proctor

Ruby Tuesday – Date#wday

Today’s Ruby Tuesday is on Date#wday.

Date#wday returns an integer value for the day of the week that the day falls on.

Date.new(2015, 4, 7).wday
# => 2
Date.new(1970, 1, 1).wday
# => 4
Date.new(1, 1, 1).wday
# => 6

The values that Date#wday can return will be between 0-6, with 0 being Sunday.

Date.new(2015, 4, 5).wday
# => 0
Date.new(2015, 4, 5).sunday?
# => true
Date.new(2015, 4, 11).wday
# => 6
Date.new(2015, 4, 11).saturday?
# => true

–Proctor

Erlang Thurday – lists:delete/2

Today’s Erlang Thursday in lists:delete/2.

lists:delete/2 takes a Erlang term as it’s first argument, and will remove that item from the list passed in as the second argument.

lists:delete(1, [8, 7, 6, 5, 4, 3, 2, 1]).
% [8,7,6,5,4,3,2]
lists:delete(4, [1, 1, 2, 3, 5, 8]).
% [1,1,2,3,5,8]
lists:delete(72, "Hello World!").
% "ello World!"
lists:delete(d, [a, b, c, d]).
% [a,b,c]
lists:delete(4, []).
% []
lists:delete({b, 2}, [{a, 1}, {b, 2}, {c, 3}]).
% [{a,1},{c,3}]
lists:delete([1, 2, 3], [[4, 5, 6], [7, 8, 9], [1, 2, 3]]).
% [[4,5,6],[7,8,9]]

Note that lists:delete/2 only removes the first item found in the list, and leaves any other occurrences of the item in the list.

€lists:delete(1, [1, 1, 2, 3, 5, 8]).
% [1,2,3,5,8]

As lists:delete/2 was a easy function to demonstrate, and leaving it at this would be a very short post, I thought it might be worth showing a how you might write a very naive1 implementation of lists:delete/2 yourself.

-module(my_lists).

-export([delete/2]).

delete(Item, List) ->
    delete(Item, [], List).

delete(Item, Checked, [Item|Rest]) ->
    lists:reverse(Checked) ++ Rest;
delete(Item, Checked, [Head|Rest]) ->
    delete(Item, [Head | Checked], Rest);
delete(_Item, Checked, []) ->
    lists:reverse(Checked).

Let’s start with our delete function as we expect it to be called from the outside world.

my_lists:delete/2 is the nice API function that just calls delete/3 which is a “private” function (not exported) so the consumer doesn’t have to worry about passing in the accumulator for the items we have checked so far, which we pass as an empty list for the initial value.

-module(my_lists).

-export([delete/2]).

delete(Item, List) ->
    delete(Item, [], List).

The first function clause of delete/3 uses pattern matching to check if the item we want to delete is also the first item in the rest of the list to check. If the pattern match succeeds, we have found the first occurrence of the item to remove! We can stop processing the list and return the result, which is the reverse of the list of items we have checked so far combined with the rest of the items we never got around to checking.

delete(Item, Checked, [Item|Rest]) ->
    lists:reverse(Checked) ++ Rest;

The second clause “knows” that the item we are wanting to delete and the first item in the rest of the list don’t match. How does it “know”? Because if they did match, the first clause would have matched and this clause would not have been evaluated. As we haven’t found the item to remove, we add the item held by Head to the list of Checked items, and then continue calling delete/3. The fact that we are passing a new list of the checked items by prepending Head to the list in Checked is why we need to reverse Checked in the first and third function clauses.

delete(Item, Checked, [Head|Rest]) ->
    delete(Item, [Head | Checked], Rest);

The third, and final, clause of delete/3 has reached the end of the list and not found the item, so we just return the list we have reversed it.

delete(_Item, Checked, []) ->
    lists:reverse(Checked).

There you have it, a very naive1 implementation of your very own version of lists:delete/2.

–Proctor

1. Naive because this is not optimized for performance, or exhaustively tested for completely accurate behavior of lists:delete/2. back