HOME       >>       Programming

Calendar And The Date () Function Making Math Simple With Modular Arithmetic


Jared

In my days of calendar making I've encountered a few minor inconveniences. When you try to make a calendar, you have to find a few specific things: (1) the first day of the month, (2) how many days are in the month, and (3) what today's date is. The second and third ones are easy to find. Before we start making a calendar, though, let's set some ground rules:

define ('TS', time ());

Now we can find (2) and (3) from above:

$total_days = (int) date ('t', TS);$todays_date = (int) date ('j', TS);

Now (1) is a different issue altogether. The way that I originally used to do it was to subtract a given date from the day of the week of that date and then add 1 and add 7 until you have a number between 0 and 6, inclusive.

$first_day = date ('w', TS) - date ('d', TS) + 1;while ($first_day < 0) $first_day += 7;

The reason for having a while statement to do what could simply be done with the modulo operator (%) is because PHP is a little bit annoying when it comes to modulo. It seems that me that when you calculate a modulo, you should always have a positive number. So:

35 % 7 = 030 % 7 = 2-35 % 7 = 0-30 % 7 = 5

However, PHP does not see eye to eye with me on this one. Unfortunately, this is what PHP tells you:

35 % 7 = 030 % 7 = 2-35 % 7 = 0-30 % 7 = [b]-2[/b]

Now the tricky part here is that while 5 and -2 may be congruent modulo 7, they are not equal if you're not talking in modulo terms. So if we want to use modulo instead of the while statement and the 20th of April is on a Sunday then we have this:

$first_day = (date ('w', TS) - date ('d', TS) + 1) % 7;$first_day = (0 - 20 + 1) % 7;$first_day = -19 % 7;$first_day = -5;

So we don't get a sensible value, as any sensible value would be positive. And the difficult part here is that you are not sure whether or not this value is negative. So if you want to use modulo, you still need an IF statement to decide whether or not to correct the negative.

But I finally came up with a better solution! Since the day of the week will never be less than 0 and the given date will never be greater than 31, the "potentially negative number" will never be less than 0 - 31 + 1 = -30. The next positive multiple of 7 larger than 30 is 35, so if we add 35 to this number it will not affect the modulo answer and it will ensure that the number is always positive.

So our equation changes from 0 - 31 + 1 to 0 - 31 + 1 + 35 = 0 - 31 + 36. So then now we can use modulo and not have to worry about IF statements or WHILE statement!

$first_day = (date ('w', TS) - date ('d', TS) + 36) % 7;

It's not like it's a particularly genius idea, but it certainly simplifies the calculation. And save a potential 4 while statements. So then if we want to turn this information into a calendar, here is a very simple script:

<?phpdefine ('TS', time ());$first_day = (date ('w', TS) - date ('d', TS) + 36) % 7;$total_days = (int) date ('t', TS);$todays_date = (int) date ('j, TS);echo '<table>' . "\r\n";echo '<tr>' . "\r\n";echo '<td align="center" colspan="7">' . date ('F Y', TS) . '</td>' . "\r\n";echo '</tr>' . "\r\n";echo '<tr>' . "\r\n";echo '<td align="center">S</td>' . "\r\n";echo '<td align="center">M</td>' . "\r\n";echo '<td align="center">T</td>' . "\r\n";echo '<td align="center">W</td>' . "\r\n";echo '<td align="center">T</td>' . "\r\n";echo '<td align="center">F</td>' . "\r\n";echo '<td align="center">S</td>' . "\r\n";echo '</tr>' . "\r\n";for ($i = 0; $i < 6; $i++) { echo '<tr>' . "\r\n"; for ($j = 0; $j < 7; $j++) { echo '<td align="center">' . (($t = $i * 7 + $j + 1 - $first_day) >= 1 && $t <= $total_days ? ($t == $todays_date ? '<b>' . $t . '</b>' : $t) : ' ') . '</td>' . "\r\n"; } echo '</tr>' . "\r\n";}echo '</table>' . "\r\n";?>

So there you have it! Any questions? Comments? Please post and let me know!


VIEW DESKTOP VERSION REGISTERGET FREE HOSTING

Xisto.com offers Free Web Hosting to its Members for their participation in this Community. We moderate all content posted here but we cannot warrant full correctness of all content. While using this site, you agree to have read and accepted our terms of use, cookie and privacy policy. Copyright 2001-2019 by Xisto Corporation. All Rights Reserved.