
![]() |
perkiset
NBs and I went back and forth on ways to handle things like "Get me the second Friday in March 2007" or "Get me the last Monday in February 2006." We have two different ways of going at it and I thought the results were pretty good.
Below is my final iteration, NBs, please post yours as well. Here is the spam for the engines: date functions in phpcomplex date functions advanced date math date calculation First Second Third Fourth Fifth Last Monday Tuesday Wednesday Thursday Friday Saturday Sunday January February March April May June July August September October November December <? php// This function returns a date-type value based on the parameters passed // Days are ISO standard: 1==Monday, 7==Sunday. // specialDate(2, 1, 6, 2007) would return the second Monday of June 2007 // specialDate(-1, 5, 1, 2006) would return the LAST Friday of January 2006. function specialDate($offset, $dayofweek, $month, $year) { if (!$offset) throw new Exception('specialDate: Parameter 0 (offset) must not be zero'); if (($dayofweek < 1) or ($dayofweek > 7)) throw new Exception('specialDate: Parameter 1 (Day Of Week) must be 1..7'); if (($month < 1) or ($month > 12)) throw new Exception('specialDate: Parameter 2 (Month) must be 1..12'); // Invert the offset such that if it's >=4 it becomes -1, or <=-4 it becomes 1... $offset = (abs($offset) >= 4) ? (($offset / abs($offset)) * -1) : $offset; if ($offset > 0) { // Make a base time the first of the target month $time = mktime(0, 0, 0, $month, 1, $year); $move = 86400; $weeks = --$offset * 604800; } else { // Make a base time the last of the target month $time = mktime(0, 0, 0, $month + 1, 1, $year) - 86400; $move = -86400; $weeks = ++$offset * 604800; } // Now find the first matching DayOfWeek... while (date('N', $time) <> $dayofweek) { $time += $move; } // return the time, offset by weeks... return $time + $weeks; } ?> nutballs
The only significant difference other than methodology is that my function recursively calls itself to determine the first occurrence in the future of the date requested, if $forcefuture is true. This is a specific need that I have for my project however, you can eliminate it by chopping out the $forcefuture parameter and the stuff noted by the comments below.
<? phpfunction specialDate($offset, $dayofweek, $month, $year, $forcefuture=false) { //error handling. this is generic do what you want. if ((abs($offset) > 5) or ($offset == 0)) { return false; } if (($dayofweek < 1) or ($dayofweek > 7)) { return false; } if (($month < 1) or ($month > 12)) { return false; } //make a base time assume the first of the month $time = mktime(0,0,0,$month,1,$year); $move = 1; //positive 1. just a single unit variable for plus or minus calcs //we want something from the end of the month. so... //increase 1 month and then decrease 1 day. puts you on last day of month if ($offset < 0) { $time = DateAdd('m', 1, $time); $time = DateAdd('d', -1, $time); $move = -1; //going backward from end of month, so move is changed to negative } // Now find the first matching DayOFWeek... while (date('N', $time) <> $dayofweek) { $time = DateAdd('d',$move,$time); //forward or back in time depending on neg/pos of $move } //determine how many weeks to add, $offset -1 //but since offset can be negative, we need to do funky math to reduce the offset value towards zero. $time=DateAdd('w',($offset/abs($offset))*(abs($offset)-1),$time); // Make sure that the offset or $weeks has not pushed me out of the target month... //roll back or forward a week to get back into month. invert $move if (date('m', $time) <> $month) { $time = DateAdd('w',-$move,$time); } //if we are forcing a future date, we recursively call this function with 1 year greater //if you dont care about enforcing future dates, you can chop out this part. if (($forcefuture) and ($time < time())) { $time = specialDate($offset, $dayofweek, $month, $year+1, $forcefuture); } //uh yea, return the timestamp of the specialdate return $time; } //a Date shifting function that deals with leapyear and crazyness like that function DateAdd($interval, $number, $time) { switch ($interval) { case 'y': $timestamp = strtotime($number.' years', $time); break; case 'm': $timestamp = strtotime($number.' months', $time); break; case 'd': $timestamp = strtotime($number.' days', $time); break; case 'w': $timestamp = strtotime($number.' weeks', $time); break; case 'h': $timestamp = strtotime($number.' hours', $time); break; case 'n': $timestamp = strtotime($number.' minutes', $time); break; case 's': $timestamp = strtotime($number.' seconds', $time); break; } return $timestamp; } ?> |

Thread Categories

![]() |
![]() |
Best of The Cache Home |
![]() |
![]() |
Search The Cache |
- Ajax
- Apache & mod_rewrite
- BlackHat SEO & Web Stuff
- C/++/#, Pascal etc.
- Database Stuff
- General & Non-Technical Discussion
- General programming, learning to code
- Javascript Discussions & Code
- Linux Related
- Mac, iPhone & OS-X Stuff
- Miscellaneous
- MS Windows Related
- PERL & Python Related
- PHP: Questions & Discussion
- PHP: Techniques, Classes & Examples
- Regular Expressions
- Uncategorized Threads