note 80866 modified in ref.datetime by danbrown

From: Date: Sun, 20 Jul 2008 02:18:09 +0000
Subject: note 80866 modified in ref.datetime by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-141948@lists.php.net to get a copy of this message
Here's my version of date diff that handles leap years, DST, and deals with the diff in terms of "human calculations". For example, this code does not assume that a year = 365.25 days, or that a month = 30/31 days. The results are exactly what a human being would determine as a good result. <?php /** * this code assumes php >= 5.1.0. if using < 5.1, read * php.net/strtotime and change the condition for checking * for failure from strtotime() */ // $t1, $t2: unix times, or strtotime parseable // $precision: max number of units to output // $abbr: if true, use "hr" instead of "hour", etc. function date_diff ($t1, $t2, $precision = 6, $abbr = false) { if (preg_match('/\D/', $t1) && ($t1 = strtotime($t1)) === false) return false; if (preg_match('/\D/', $t2) && ($t2 = strtotime($t2)) === false) return false; if ($t1 > $t2) list($t1, $t2) = array($t2, $t1); $diffs = array( 'year' => 0, 'month' => 0, 'day' => 0, 'hour' => 0, 'minute' => 0, 'second' => 0, ); $abbrs = array( 'year' => 'yr', 'month' => 'mth', 'day' => 'day', 'hour' => 'hr', 'minute' => 'min', 'second' => 'sec' ); foreach (array_keys($diffs) as $interval) { while ($t2 >= ($t3 = strtotime("+1 ${interval}", $t1))) { $t1 = $t3; ++$diffs[$interval]; } } $stack = array(); foreach ($diffs as $interval => $num) $stack[] = array($num, ($abbr ? $abbrs[$interval] : $interval) . ($num != 1 ? 's' : '')); $ret = array(); while (count($ret) < $precision && ($item = array_shift($stack)) !== null) { if ($item[0] > 0) $ret[] = "{$item[0]} {$item[1]}"; } return implode(', ', $ret); } $t1 = 'Feb 4, 2008 12:16:00'; $t2 = 'Jul 3, 2006 16:15:30'; echo date_diff($t1, $t2), "\n", date_diff($t1, $t2, 3), "\n", date_diff($t1, $t2, 2, true), "\n"; ?> --was-- Here's my version of date diff that handles leap years, DST, and deals with the diff in terms of "human calculations". For example, this code does not assume that a year = 365.25 days, or that a month = 30/31 days. The results are exactly what a human being would determine as a good result. <? /** * this code assumes php >= 5.1.0. if using < 5.1, read * php.net/strtotime and change the condition for checking * for failure from strtotime() */ // $t1, $t2: unix times, or strtotime parseable // $precision: max number of units to output // $abbr: if true, use "hr" instead of "hour", etc. function date_diff ($t1, $t2, $precision = 6, $abbr = false) { if (preg_match('/\D/', $t1) && ($t1 = strtotime($t1)) === false) return false; if (preg_match('/\D/', $t2) && ($t2 = strtotime($t2)) === false) return false; if ($t1 > $t2) list($t1, $t2) = array($t2, $t1); $diffs = array( 'year' => 0, 'month' => 0, 'day' => 0, 'hour' => 0, 'minute' => 0, 'second' => 0, ); $abbrs = array( 'year' => 'yr', 'month' => 'mth', 'day' => 'day', 'hour' => 'hr', 'minute' => 'min', 'second' => 'sec' ); foreach (array_keys($diffs) as $interval) { while ($t2 >= ($t3 = strtotime("+1 ${interval}", $t1))) { $t1 = $t3; ++$diffs[$interval]; } } $stack = array(); foreach ($diffs as $interval => $num) $stack[] = array($num, ($abbr ? $abbrs[$interval] : $interval) . ($num != 1 ? 's' : '')); $ret = array(); while (count($ret) < $precision && ($item = array_shift($stack)) !== null) { if ($item[0] > 0) $ret[] = "{$item[0]} {$item[1]}"; } return implode(', ', $ret); } $t1 = 'Feb 4, 2008 12:16:00'; $t2 = 'Jul 3, 2006 16:15:30'; echo date_diff($t1, $t2), "\n", date_diff($t1, $t2, 3), "\n", date_diff($t1, $t2, 2, true), "\n"; ?> http://php.net/manual/en/ref.datetime.php

« previous php.notes (#141948) next »