Pergunta

I have a function that calculate the days difference between two dates:

function daysBetweenDates($startDate, $endDate) {
  list($year1, $month1, $day1) = explode('-', $startDate);
  list($year2, $month2, $day2) = explode('-', $endDate);
  $f = mktime(0, 0, 0, $month2, $day2, $year2);
  $i = mktime(0, 0, 0, $month1, $day1, $year1);
  $difference =  $f - $i;
  $days = floor($difference/86400);
  return $days;
}

The problem is that this code is getting weird results with some dates. For example if the $startDate = '2014-10-14' and $endDate = '2014-10-28', the output of this function everywhere is 14, but i am getting 13.
I have checked some online php interpreters and for some goddamn reason i don't know why, my mktime is returning me different values.

Example:

on 3v4l.org running mktime(0, 0, 0, 10, 28, 2014) returns 1414450800 for PHP versions 5.1.0 - 5.5.8
on 3v4l.org running mktime(0, 0, 0, 10, 14, 2014) returns 1413237600 for PHP versions 5.1.0 - 5.5.8
The output of the function with these values is 14.

In my code, when i run the same values on mktime i get 1414461600 and 1413255600 respectively. Running this code the output of the function is 13.

And i am running on PHP 5.3.3.

Any help on understanding what is wrong with my environment/php configuration/function error/bad code will be great appreciated.

Foi útil?

Solução

Using DateTime rather than mktime will end your hell:-

function daysBetweenDates($startDate, $endDate) {
  $startDate = new \DateTime($startDate);
  $endDate = new \DateTime($endDate);
  return $startDate->diff($endDate)->days;
}

Should get you close to what you need. It will take into account any DST changes under the hood, which is probably your issue as DST (in UK anyway) ends on 26th October this year.

For your example dates, this returns 14

Reference http://php.net/datetime

Outras dicas

The value of mktime is based on your current timezone. The values you give to mktime are "wall clock time", it returns an absolute point-in-human-history UNIX timestamp. For this it needs to consider your current timezone, set by date_default_timezone_set. If there's a DST transition in between these two times, there may be an hour more or less between these two wall clock times than in other timezones. Therefore, a day is not guaranteed to be exactly 86400 seconds long, and you're stumbling across this problem here. In short: this is too naïve a way of doing time difference calculations, because you're ignoring all the factors that make human times so messy. See @vascowhite's answer for how to use the existing libraries that do take all that into account.

Return of function mktime() is based on current timezone set.

If you wish to return timestamp for GMT date, then just use function gmmktime().

Or, you can set parameter $is_dst in function mktime() to 0, which means that DST is ignored.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top