Tag Archives: Erlang Thurday

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.


Erlang Thursday – calendar:local_time_to_universal_time_dst/1

In honor of the time change this weekend, today’s Erlang Thursday is on calendar:local_time_to_universal_time_dst/1.

To better understand what calendar:local_time_to_universal_time_dst/1 is doing, it will be contrasted to calendar:local_time_to_universal_time/1.

This coming Sunday is we move the clock forward an hour at 2 AM, so let us see what the time is in UTC right at 1:59 AM.

% {{2015,3,8},{7,59,59}}

Now let’s see what calendar:local_time_to_universal_time/1 returns for 2 AM, which we never actually hit, since the time changes straight to 3 AM.

% {{2015,3,8},{8,0,0}}

But as we dig into the library we see that there is also calendar:local_time_to_universal_time_dst/1. calendar:local_time_to_universal_time_dst/1 returns a list of time tuples, and we start to see why this is important.

This time, let’s call calendar:local_time_to_universal_time_dst/1 with the 2 AM hour and see what is returned.

% []

An empty list!

This makes sense if you take a moment to think about it, as 2 AM doesn’t ever happen so there is no UTC time that it would map to.

And if we look at what happens when we make the jump to 3 AM, we get 8 AM UTC, which is just a second later in UTC, then the time in UTC at 1:59:59 AM.

% [{{2015,3,8},{8,0,0}}]

That covers the case for this coming weekend, so let is check out what is going to happen later this year on November 1st when the clocks move back an hour.

To start with a baseline, let’s see what time it is in UTC at 12:59:59 AM, as we know we only encounter that time once.

% {{2015,11,1},{5,59,59}}
% [{{2015,11,1},{5,59,59}}]

And even though the time change happens a 2 AM, we still only encounter that once, as we move straight to 1 AM the first time.

% [{{2015,11,1},{8,0,0}}]

So at 12:59:59 AM, we are at 5:59:59 AM UTC, and at 2 AM we are at 8 AM UTC. Now comes the tricky part, 1 AM.

1 AM is an odd case, as we will live through 1 AM twice that night. So let’s see what Erlang does with that.

First, we see what time it is in UTC when we call calendar:local_time_to_universal_time with 1 AM.

% {{2015,11,1},{6,0,0}}

We get 6 AM UTC. We move from 5:59:59 AM UTC to 6 AM UTC; and that makes sense, until we start to wonder about the second time we encounter 1 AM.

Now, let’s see what time it is in UTC when we call calendar:local_time_to_universal_time_dst/1 with 1 AM.

% [{{2015,11,1},{6,0,0}},{{2015,11,1},{7,0,0}}]

We get a list with two times in UTC, one for 6 AM UTC when we encounter 1 AM the first time, and one for 7 AM UTC for when we encounter 1 AM the second time around. This happens for every time in the 1 AM hour as well.

% [{{2015,11,1},{6,59,59}},{{2015,11,1},{7,59,59}}]

By returning a list of either no items, one item, or two items, Erlang gives you the most accurate information for you to use, and allow for you to make the informed decision for how you are expecting to handle the times, instead of making some of the decisions for you even if they don’t align with your system’s view of the world.