Get the next, or previous day of week from the current date

Given a date, get the next or previous Monday, or Tuesday etc from the given date. This is useful when working with ical recurring dates.  If the date given is already that day of week, it is returned as the result.

For example to get the following

Every 20th Monday of the year, forever:
DTSTART;TZID=US-Eastern:19970519T090000
RRULE:FREQ=YEARLY;BYDAY=20MO

==> (1997 9:00 AM EDT)May 19
(1998 9:00 AM EDT)May 18
(1999 9:00 AM EDT)May 17

One could get the first Monday of the year, the it is fairly easy to get the 20th !

<?php

global $amr_day_of_week_no;
$amr_day_of_week_no = array (
 'MO' => 1,
 'TU' => 2,
 'WE' => 3,
 'TH' => 4,
 'FR' => 5,
 'SA' => 6,
 'SU' => 0
 );    

 function amr_goto_byday ($dateobj, $byday, $sign)    {
 global $amr_day_of_week_no;    
 $dayofweek = $dateobj->format('w'); /* 0=sunday, 6 = saturday */
 if ($dayofweek == '-1') $dayofweek = get_oldweekdays($dateobj); /* php seems to break around 1760   */
$target     = $amr_day_of_week_no[$byday]; /*  mo=1 ,su=7  */
 $adjustment = $target - $dayofweek;
 if ($sign === '+') {
 if ($adjustment < 0) $adjustment = $adjustment + 7;        
 }
 else if ($adjustment > 0) $adjustment = $adjustment-7;    
 $d2 = new DateTime();
 $d2 = clone ($dateobj);         
 date_modify ($d2,$adjustment.' days');    
 return ($d2);
 }    

 /* --------Test data ------------------------- */
$d[] = new DateTime('2009-12-25');
$d[] = new DateTime('2009-12-28');
$d[] = new DateTime('2009-12-29');
$d[] = new DateTime('2009-12-30');
$d[] = new DateTime('2009-12-31');
$d[] = new DateTime('2010-01-01');
$d[] = new DateTime('2010-01-02');
$d[] = new DateTime('2010-01-03');
$d[] = new DateTime('2010-01-04');
$d[] = new DateTime('2010-01-05');
$d[] = new DateTime('2010-01-06');
$d[] = new DateTime('2010-01-07');
$d[] = new DateTime('2010-01-08');
$d[] = new DateTime('2010-01-09');
$d[] = new DateTime('2010-01-10');
$d[] = new DateTime('2010-01-11');

echo '<table>';    
foreach (array ('TU','WE','TH','FR','SA','SU','MO') as $day) {
 echo '<tr><td> Aiming for '.$day.'</td><td>If not this, then next</td><td>If not this, then prev</td></tr>';                
 foreach ($d as $i => $d2)    {
 $d3 = amr_goto_byday ($d2, $day, '+');
 $d4 = amr_goto_byday ($d2, $day, '-');
 $s = $d2->format('Y m d l');
 echo '<tr><td> '.$s.'</td><td>'.$d3->format('l,Y m d').'</td><td>'.$d4->format('l,Y m d').'</td></tr>';
 }    
}
echo '</table>';   
  
?>

Day of week for historical dates earlier than 1760

One of the ics files that I encountered in testing my events list plugin came from Google and had a “Zero Year” date in it.  There were probably reasons for this and I have to be thankful for the happening –   In looking into it I foundthat the php date format function for day of week $dateobj->format(‘w’);  “breaks” around the year 1760 and starts returning a “-1”.  Since I do have people using my plugin for anniversaries with earlier start dates (It’s not all musical gigs and sporting events!), I felt I needed to cope with it.

I now use the following code, which appears to work when comparing the weekdays using http://www.searchforancestors.com/utility/dayofweek.html

$w = $dateobj->format('w');
if ($w == '-1') $w = get_oldweekdays($dateobj);

function get_oldweekdays ($d) {
   $dummy = new DateTime();
   $dummy = clone ($d);
   date_modify($dummy,'+91500 weeks'); 
   /* add weeks to get us back to a "working" date - 
   a guess from when the date started breaking, plus some extra to be safe */
   $w = $dummy->format('w');
 return($w);
}

Stop obfuscating your email addresses!

Please, please… it is simply not worth it – the spambots veryquickly catch on to any new method, and they will harvest your email address somehow.  If not from your website, then from your friends contact list, or that greeting card or party invitation sent via a website.

You are simply wasting your time and making it harder for your valid visitors and for valid emails to get t o you..

Jason Priem puts the case fairly well.

So what to do?

Use a good spam filter.    Gmail does the best job so far and yes you can continue to use your domain name email.

I have the following setup:

  1. email@domain is forwarded to Gmail
  2. Gmail set to send as email@domain
  3. Email software (outlook or thunderbird for eg) set to use IMAP against Gmail (use folders and lables work well together, are synschronised)

This means that I have a local backup of everything that is on gmail (yes – maybe gears is also kinda a local backup), and should Gmail fail, I simply unforward from my domain email and start accessing it directly from the email package.

A while back when Gmail seemed a bit slow, I tried taking it out of the loop, but with a couple of weeks was back again – their accuracy in handling spam is amazing, less spam and less false positives – this makes all the difference.

Some detail on the battle.