[PHP-DEV] Bug #1966: gmmktime is applies wrong offset in wrong direction. From: dairiki <email protected>
Date: 08/04/99

From: dairiki <email protected>
Operating system: Linux 2.0.10 / libc.so.5.4.46
PHP version: 3.0.12
PHP Bug Type: Misbehaving function
Bug description: gmmktime is applies wrong offset in wrong direction.

<? echo gmdate("d M Y H:i:s\n", gmmktime(1,2,3,4,5,1996));
echo gmdate("d M Y H:i:s\n", gmmktime(1,2,3,8,5,1996)); ?>

Produces:

05 Apr 1996 17:02:03
05 Aug 1996 17:02:03

I am in the US/Pacific timezone. The above times are off by 16 hours (twice the
PST/UTC difference.)

In general, I am not convinced that relying on (the libc) mktime() to
do the right thing is a robust practice. It may be better to find the timezone
offset interatively by alternate calls to mktime() and gmtime(). As an example,
here's the php3 code I'm currently using in place of (the broken) gmmktime():

function working_gmmktime($h,$m,$s,$mon,$mday,$year)
{
  static $offset;
  
  $time = mktime($h, $m, $s, $mon, $mday, $year);

  $gmday = gmdate("Ymd", $time + $offset);
  $day = date("Ymd", $time);
  
  while ($gmday != $day)
    {
      $offset += $gmday < $day ? 12 : -12;
      $gmday = gmdate("Ymd", $time + $offset);
    }

  $hour = gmdate("H", $time + $offset);
  $min = gmdate("i", $time + $offset);
  $offset += (($h - $hour) * 60 + ($m - $min)) * 60;

  return $time + $offset;
}

A second unexercised bug was found by inspection of functions/datetime.c(176):

                gmadjust_hour = gmadjust / 3600;
                gmadjust_min = gmadjust - gmadjust_hour * 3600;

(gmadjust is in seconds --- there needs to be another divide by 60 in the
second line.) Of course this bug only bites if the timezone offset is not
an integral number of hours.

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: php-dev-unsubscribe <email protected>
For additional commands, e-mail: php-dev-help <email protected>
To contact the list administrators, e-mail: php-list-admin <email protected>