Jump to content
xisto Community
Jared

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

Recommended Posts

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!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.