<p>How do you actually perform datetime operations such as adding date, finding difference, find out how many days excluding weekends in an interval? I personally started to pass some of these operations to my postgresql dbms as typically I would only need to issue one sql statement to obtain an answer, however, to do it in PHP way I would have to write a lot more code that means more chances for errors to occur...</p>

<p>Are there any libraries in PHP that does datetime operation in a way that don't require a lot of code? that beats sql in a situation where 'Given two dates, how many workdays are there between the two dates? Implement in either SQL, or $pet_lang' that is solved by making this query?</p>

<pre class="lang-sql prettyprint-override"><code>SELECT  COUNT(*) AS total_days
FROM    (SELECT date '2008-8-26' + generate_series(0,
          (date '2008-9-1' - date '2008-8-26')) AS all_days) AS calendar
WHERE   EXTRACT(isodow FROM all_days) &lt; 6;
</code></pre>

[{'answer_id': 56595, 'author': 'reefnet_alex', 'author_id': 2745, 'author_profile': 'https://Stackoverflow.com/users/2745', 'pm_score': 3, 'selected': False, 'text': '<p>While for most datetime operations I would normally convert to Unixtime and perform addition subtraction etc. on the Unixtime integer, you may want to look at the Zend framework Zend_Date class. </p>\n\n<p>This has a lot of the functionality you describe. Although Zend is billed as a "framework" it works exceptionally well as a class library to pick and chose elements from. We routinely include it in projects and then just pull in bits as and when we need them. </p>\n'}, {'answer_id': 56606, 'author': 'Jarrett Meyer', 'author_id': 5834, 'author_profile': 'https://Stackoverflow.com/users/5834', 'pm_score': 1, 'selected': False, 'text': '<p>The easiest method is to use a timestamp, representing the number of seconds since January 1, 2008. With a timestamp type, you can do things like...</p>\n\n<pre><code>now = time();\ntomorrow = now + 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds\n</code></pre>\n\n<p>Check out the documentation for <a href="http://us2.php.net/manual/en/function.time.php" rel="nofollow noreferrer">time()</a>, <a href="http://us2.php.net/manual/en/function.date.php" rel="nofollow noreferrer">date()</a> and <a href="http://us2.php.net/manual/en/function.mktime.php" rel="nofollow noreferrer">mktime()</a> on the php web pages. Those are the three methods that I tend to use the most frequently.</p>\n'}, {'answer_id': 56900, 'author': 'Rushi', 'author_id': 3983, 'author_profile': 'https://Stackoverflow.com/users/3983', 'pm_score': 0, 'selected': False, 'text': '<p>You can use a combination of <a href="http://php.net/strtotime" rel="nofollow noreferrer">strtotime</a>, <a href="http://php.net/mktime" rel="nofollow noreferrer">mktime</a> and <a href="http://php.net/date" rel="nofollow noreferrer">date</a> todo the arithmetic</p>\n\n<p>Here is an example which uses a combo todo some arithmetic <a href="http://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/" rel="nofollow noreferrer">http://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/</a> I\'ll reproduce the code here for simplicity\n    \n\n<pre><code>if ($timestamp_diff &lt; (60*60*24*7)) {\n   echo floor($timestamp_diff/60/60/24)." Days";\n} elseif ($timestamp_diff &gt; (60*60*24*7*4)) {\n   echo floor($timestamp_diff/60/60/24/7)." Weeks";\n} else {\n   $total_months = $months = floor($timestamp_diff/60/60/24/30);\n   if($months &gt;= 12) {\n      $months = ($total_months % 12);\n      $years&amp;nbsp; = ($total_months - $months)/12;\n      echo $years . " Years ";\n   }\n   if($months &gt; 0)\n      echo $months . " Months";\n}\n?&gt;\n</code></pre>\n'}, {'answer_id': 56930, 'author': 'Jeffrey04', 'author_id': 5742, 'author_profile': 'https://Stackoverflow.com/users/5742', 'pm_score': 0, 'selected': False, 'text': "<p>@Rushi I don't like strtotime() personally.. i don't know why but i discovered this morning that passing a string like this '2008-09-11 9:5 AM' to strtotime returns a false...</p>\n\n<p>I don't think the code you provided solve the example problem 'Given two dates, how many workdays are there between the two dates? Implement in either SQL, or $pet_lang' and I haven't consider if I have a list of public holiday...</p>\n"}, {'answer_id': 57039, 'author': 'Darryl Hein', 'author_id': 5441, 'author_profile': 'https://Stackoverflow.com/users/5441', 'pm_score': 2, 'selected': False, 'text': '<p><a href="https://pear.php.net/package/Date" rel="nofollow noreferrer"><code>PEAR::Date</code></a> looks like it might have some useful functionality.</p>\n\n<p><a href="https://pear.php.net/package/Calendar" rel="nofollow noreferrer"><code>PEAR::Calendar</code></a> might also be useful.</p>\n'}, {'answer_id': 57717, 'author': 'Laith', 'author_id': 5961, 'author_profile': 'https://Stackoverflow.com/users/5961', 'pm_score': 2, 'selected': False, 'text': '<p>strtotime() is useful but it does have some odd behaviors that can pop-up from time to time if you are not just using it to convert a formatted date/time string.</p>\n\n<p>things like "+1 month" or "-3 days" can sometimes not give you what you expect it to output.</p>\n'}, {'answer_id': 58545, 'author': 'ralfe', 'author_id': 340241, 'author_profile': 'https://Stackoverflow.com/users/340241', 'pm_score': 0, 'selected': False, 'text': '<p>If you have a look at <a href="http://php.net/date" rel="nofollow noreferrer">http://php.net/date</a> , you will find some examples of using <code>mktime()</code> to perform operations.</p>\n\n<p>A simple example would be to workout what tomorrows date would be. You can do that by simply adding 1, to the day value in <code>mktime()</code> as follows:</p>\n\n<pre><code>$tomorrow = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")));\n</code></pre>\n\n<p>So here, you will receive a date in the form of YYYY-MM-DD containing tomorrows date. You can also subtract days by simply replacing \'+\' with \'-\'. <code>mktime()</code> makes life a lot easier, and saves you from having to do nested if statements and other such troublesome coding.</p>\n'}, {'answer_id': 58603, 'author': 'Vertigo', 'author_id': 5468, 'author_profile': 'https://Stackoverflow.com/users/5468', 'pm_score': 0, 'selected': False, 'text': '<p>You can get number of days between two dates like this:</p>\n\n<pre><code>$days = (strtotime("2008-09-10") - strtotime("2008-09-12")) / (60 * 60 * 24);\n</code></pre>\n\n<p>And you can make function something like that (I don\'t have php installed in my work computer so i can\'t guarantee syntax is 100% correct)</p>\n\n<pre><code>function isWorkDay($date)\n{\n // check if workday and return true if so\n}\n\nfunction numberOfWorkDays($startdate, $enddate)\n{\n  $workdays = 0;\n  $tmp = strtotime($startdate);\n  $end = strtotime($enddate);\n  while($tmp &lt;= $end)\n  {\n    if ( isWorkDay( date("Y-m-d",$tmp) ) ) $workdays++;\n    $tmp += 60*60*24;\n  }\n  return $workdays;\n}\n</code></pre>\n\n<p>If you don\'t like strtotime and you always have date in same format you can use explode function like </p>\n\n<pre><code>list($year, $month, day) = explode("-", $date);\n</code></pre>\n'}, {'answer_id': 60699, 'author': 'JW.', 'author_id': 4321, 'author_profile': 'https://Stackoverflow.com/users/4321', 'pm_score': 0, 'selected': False, 'text': '<p>I would strongly recommend using PHP 5.2\'s <a href="http://us2.php.net/datetime" rel="nofollow noreferrer">DateTime objects</a>, rather than using UNIX timestamps, when doing date calculations. When you use the PHP date functions that return UNIX timestamps, you have a very limited range to work with (e.g. nothing before 1970).</p>\n'}, {'answer_id': 201180, 'author': 'user13414', 'author_id': 13414, 'author_profile': 'https://Stackoverflow.com/users/13414', 'pm_score': 3, 'selected': True, 'text': '<p>PHP5+\'s DateTime object is useful because it is leap time and\ndaylight savings aware, but it needs some extension to really\nsolve the problem. I wrote the following to solve a similar problem.\nThe find_WeekdaysFromThisTo() method is brute-force, but it works reasonably quickly if your time span is less than 2 years.</p>\n\n<pre><code>$tryme = new Extended_DateTime(\'2007-8-26\');\n$newer = new Extended_DateTime(\'2008-9-1\');\n\nprint \'Weekdays From \'.$tryme-&gt;format(\'Y-m-d\').\' To \'.$newer-&gt;format(\'Y-m-d\').\': \'.$tryme -&gt; find_WeekdaysFromThisTo($newer) ."\\n";\n/*  Output:  Weekdays From 2007-08-26 To 2008-09-01: 265  */\nprint \'All Days From \'.$tryme-&gt;format(\'Y-m-d\').\' To \'.$newer-&gt;format(\'Y-m-d\').\': \'.$tryme -&gt; find_AllDaysFromThisTo($newer) ."\\n";\n/*  Output:  All Days From 2007-08-26 To 2008-09-01: 371   */\n$timefrom = $tryme-&gt;find_TimeFromThisTo($newer);\nprint \'Between \'.$tryme-&gt;format(\'Y-m-d\').\' and \'.$newer-&gt;format(\'Y-m-d\').\' there are \'.\n      $timefrom[\'years\'].\' years, \'.$timefrom[\'months\'].\' months, and \'.$timefrom[\'days\'].\n      \' days.\'."\\n";\n/*  Output: Between 2007-08-26 and 2008-09-01 there are 1 years, 0 months, and 5 days. */\n\nclass Extended_DateTime extends DateTime {\n\n    public function find_TimeFromThisTo($newer) {\n        $timefrom = array(\'years\'=&gt;0,\'months\'=&gt;0,\'days\'=&gt;0);\n\n        // Clone because we\'re using modify(), which will destroy the object that was passed in by reference\n        $testnewer = clone $newer;\n\n        $timefrom[\'years\'] = $this-&gt;find_YearsFromThisTo($testnewer);\n        $mod = \'-\'.$timefrom[\'years\'].\' years\';\n        $testnewer -&gt; modify($mod);\n\n        $timefrom[\'months\'] = $this-&gt;find_MonthsFromThisTo($testnewer);\n        $mod = \'-\'.$timefrom[\'months\'].\' months\';\n        $testnewer -&gt; modify($mod);\n\n        $timefrom[\'days\'] = $this-&gt;find_AllDaysFromThisTo($testnewer);\n        return $timefrom;\n    } // end function find_TimeFromThisTo\n\n\n    public function find_YearsFromThisTo($newer) {\n        /*\n        If the passed is:\n        not an object, not of class DateTime or one of its children,\n        or not larger (after) $this\n        return false\n        */\n        if (!is_object($newer) || !($newer instanceof DateTime) || $newer-&gt;format(\'U\') &lt; $this-&gt;format(\'U\'))\n            return FALSE;\n        $count = 0;\n\n        // Clone because we\'re using modify(), which will destroy the object that was passed in by reference\n        $testnewer = clone $newer;\n\n        $testnewer -&gt; modify (\'-1 year\');\n        while ( $this-&gt;format(\'U\') &lt; $testnewer-&gt;format(\'U\')) {\n            $count ++;\n            $testnewer -&gt; modify (\'-1 year\');\n        }\n        return $count;\n    } // end function find_YearsFromThisTo\n\n\n    public function find_MonthsFromThisTo($newer) {\n        /*\n        If the passed is:\n        not an object, not of class DateTime or one of its children,\n        or not larger (after) $this\n        return false\n        */\n        if (!is_object($newer) || !($newer instanceof DateTime) || $newer-&gt;format(\'U\') &lt; $this-&gt;format(\'U\'))\n            return FALSE;\n\n        $count = 0;\n        // Clone because we\'re using modify(), which will destroy the object that was passed in by reference\n        $testnewer = clone $newer;\n        $testnewer -&gt; modify (\'-1 month\');\n\n        while ( $this-&gt;format(\'U\') &lt; $testnewer-&gt;format(\'U\')) {\n            $count ++;\n            $testnewer -&gt; modify (\'-1 month\');\n        }\n        return $count;\n    } // end function find_MonthsFromThisTo\n\n\n    public function find_AllDaysFromThisTo($newer) {\n        /*\n        If the passed is:\n        not an object, not of class DateTime or one of its children,\n        or not larger (after) $this\n        return false\n        */\n        if (!is_object($newer) || !($newer instanceof DateTime) || $newer-&gt;format(\'U\') &lt; $this-&gt;format(\'U\'))\n            return FALSE;\n\n        $count = 0;\n        // Clone because we\'re using modify(), which will destroy the object that was passed in by reference\n        $testnewer = clone $newer;\n        $testnewer -&gt; modify (\'-1 day\');\n\n        while ( $this-&gt;format(\'U\') &lt; $testnewer-&gt;format(\'U\')) {\n            $count ++;\n            $testnewer -&gt; modify (\'-1 day\');\n        }\n        return $count;\n    } // end function find_AllDaysFromThisTo\n\n\n    public function find_WeekdaysFromThisTo($newer) {\n        /*\n        If the passed is:\n        not an object, not of class DateTime or one of its children,\n        or not larger (after) $this\n        return false\n        */\n        if (!is_object($newer) || !($newer instanceof DateTime) || $newer-&gt;format(\'U\') &lt; $this-&gt;format(\'U\'))\n            return FALSE;\n\n        $count = 0;\n\n        // Clone because we\'re using modify(), which will destroy the object that was passed in by reference\n        $testnewer = clone $newer;\n        $testnewer -&gt; modify (\'-1 day\');\n\n        while ( $this-&gt;format(\'U\') &lt; $testnewer-&gt;format(\'U\')) {\n            // If the calculated day is not Sunday or Saturday, count this day\n            if ($testnewer-&gt;format(\'w\') != \'0\' &amp;&amp; $testnewer-&gt;format(\'w\') != \'6\')\n                $count ++;\n            $testnewer -&gt; modify (\'-1 day\');\n        }\n        return $count;\n    } // end function find_WeekdaysFromThisTo\n\n    public function set_Day($newday) {\n        if (is_int($newday) &amp;&amp; $newday &gt; 0 &amp;&amp; $newday &lt; 32 &amp;&amp; checkdate($this-&gt;format(\'m\'),$newday,$this-&gt;format(\'Y\')))\n            $this-&gt;setDate($this-&gt;format(\'Y\'),$this-&gt;format(\'m\'),$newday);\n    } // end function set_Day\n\n\n    public function set_Month($newmonth) {\n        if (is_int($newmonth) &amp;&amp; $newmonth &gt; 0 &amp;&amp; $newmonth &lt; 13)\n            $this-&gt;setDate($this-&gt;format(\'Y\'),$newmonth,$this-&gt;format(\'d\'));\n    } // end function set_Month\n\n\n    public function set_Year($newyear) {\n        if (is_int($newyear) &amp;&amp; $newyear &gt; 0)\n            $this-&gt;setDate($newyear,$this-&gt;format(\'m\'),$this-&gt;format(\'d\'));\n    } // end function set_Year\n} // end class Extended_DateTime\n</code></pre>\n'}, {'answer_id': 2013493, 'author': 'Vince Bowdren', 'author_id': 174843, 'author_profile': 'https://Stackoverflow.com/users/174843', 'pm_score': 2, 'selected': False, 'text': "<p>For adding a date, you can use the method <strong>DateTime::add</strong> (<em>Adds an amount of days, months, years, hours, minutes and seconds to a DateTime object</em>), available from php 5.3.0 onwards.</p>\n\n<p>To find the difference between two dates, there's the <strong>DateTime::diff</strong> method; but there doesn't seem to be a method for counting the working days between two dates.</p>\n"}, {'answer_id': 6645826, 'author': 'helmi03', 'author_id': 169469, 'author_profile': 'https://Stackoverflow.com/users/169469', 'pm_score': -1, 'selected': False, 'text': '<p>to get working days/holidays, postgresql CTE ftw -- see <a href="http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/" rel="nofollow">http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/</a></p>\n'}]
['https://Stackoverflow.com/questions/56568', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/5742/']