[umala] Date and Time Calculation

mira

Новичок
[umala] Date and Time Calculation

При передаче некоторых отрицательных параметров в PHP-функции времени - PHP 4.0 вместе с Апачи вылетает в трубу под Microsoft Windows.

Поэтому и был написан следующий класс-врапер.

Каковы будут коментарии и замечания?

Код:
<?php
//**************************************************************************
//
// Required: PHP Version 4.0.0
//
//**************************************************************************
//
// Date-Time calculation
//
//**************************************************************************

/**
 * Date-Time calculation class (in range 1970.01.01 00:00:00 - 2038.01.19 03:14:07).
 *
 * @author     Mira
 * @package    Umala
 */
class TTime
  {

  /**
   * Returns associative array containing information about a time-zone and Daylight Saving Time.
   *
   * $result['timezone'] - time-zone (in seconds).
   * $result['dstime']   - Daylight Saving Time (in seconds).
   *
   * @static static
   * @access public
   * @return array
   */
  function temezone()
    {
    static $params = null;
    if (!$params)
      {
      $params = gettimeofday();
      $params = array('timezone' => (-$params['minuteswest'] * 60), 'dstime' => $params['dsttime'] * 3600);
      }
    return $params;
    }


  /**
   * Converts given timestamp to the date-time array or given date-time array to the timestamp.
   *
   * @static static
   * @access public
   * @param array|int Timestamp or the date-time array
   * @return array|int|bool
   */

  function convert($mixed)
    {
    static $monthDays      = null;
    static $pastMonthsDays = null;
    if (!$monthDays)
      {
      $monthDays = array(
        array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
        array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
      $pastMonthsDays = array(
        array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334),
        array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335));
      }

    if (is_array($mixed))
      {

      $mixed = array_merge(array('year' => 1970, 'month' => 1, 'day' => 1, 'hour' =>0, 'minute' => 0, 'second' => 0), $mixed);

      if ($mixed['year'] < 1970 || $mixed['year'] > 2038)
        return false;

      $isLeap = !($mixed['year'] % 4) && (($mixed['year'] % 100) || !($mixed['year'] % 400));

      --$mixed['year'];
      --$mixed['month'];
      --$mixed['day'];

      if ($mixed['month'] < 0 || $mixed['month'] > 11)
        return false;
      if ($mixed['day'] < 0 || $mixed['day'] >= $monthDays[$isLeap][$mixed['month']])
        return false;
      if ($mixed['hour'] < 0 || $mixed['hour'] > 23)
        return false;
      if ($mixed['minute'] < 0 || $mixed['minute'] > 59)
        return false;
      if ($mixed['second'] < 0 || $mixed['second'] > 59)
        return false;

      $mixed = ($mixed['day'] + $pastMonthsDays[$isLeap][$mixed['month']] + $mixed['year'] * 365 +
        (int)($mixed['year'] / 4) - (int)($mixed['year'] / 100) + (int)($mixed['year'] / 400) - 719162) * 86400 +
        $mixed['hour'] * 3600 + $mixed['minute'] * 60 + $mixed['second'];

      if ($mixed < 0 || $mixed > 2147483647)
        return false;
      }
    else
      {
      if ($mixed < 0 || $mixed > 2147483647)
        return false;

      $datetime = array();

      $daycount = (int) ($mixed / 86400);
      $dayclock =       ($mixed % 86400);

      $weekday  = ($daycount + 3) % 7 + 1;

      $isLeap = 0;

      $temptime = (int) ($daycount / 1461);
      $daycount =       ($daycount % 1461);

      $temptime = ($temptime * 4) + 70;
      if ($daycount >= 365)
        {
        $temptime++;
        $daycount -= 365;
        if ($daycount >= 365)
          {
          $temptime++;
          $daycount -= 365;
          if ($daycount >= 366)
            {
            $temptime++;
            $daycount -= 366;
            }
          else
            {
            $isLeap++;
            }
          }
        }

      for ($month = 11; $daycount < $pastMonthsDays[$isLeap][$month]; --$month);

      $mixed = array(
        'timestamp'   => $mixed,
        'year'        => 1900 + $temptime,
        'month'       => $month+1,
        'day'         => $daycount - $pastMonthsDays[$isLeap][$month] + 1,
        'hour'        => (int) ($dayclock / 3600),
        'minute'      => (int) (($dayclock % 3600) / 60),
        'second'      => $dayclock % 60,
        'daysInYear'  => 365 + $isLeap,
        'daysInMonth' => $monthDays[$isLeap][$month],
        'dayOfYear'   => $daycount,
        'dayOfWeek'   => $weekday,
        );

      }

    return $mixed;
    }


  /**
   * Returns timestamp of a given date-time information.
   *
   * @static static
   * @access public
   * @param int year Year
   * @param int month Month
   * @param int day Day
   * @param int hour Hour
   * @param int minute Minute
   * @param int second Second
   * @return int|bool
   */
  function timestamp($year, $month, $day, $hour, $minute, $second)
    {
    return TTime::convert(
      array(
        'year'    => $year,
        'month'   => $month,
        'day'     => $day,
        'hour'    => $hour,
        'minute'  => $minute,
        'second'  => $second));
    }


  /**
   * Returns associative array containing date-time information of a given timestamp.
   * 
   * $result['timestamp']   - given timestamp.
   * $result['year']        - year.
   * $result['month']       - month.
   * $result['hour']        - hour.
   * $result['minute']      - minute.
   * $result['second']      - second.
   * $result['daysInYear']  - number of days in the year.
   * $result['daysInMonth'] - number of days in the month.
   * $result['dayOfYear']   - numeric representation of the day of the year.
   * $result['dayOfWeek']   - numeric representation of the day of the week (Monday = 0).
   *
   * @static static
   * @access public
   * @param int timestamp Timestamp
   * @return array|bool
   */
  function datetime($timestamp)
    {
    return TTime::convert($timestamp);
    }


  /**
   * Returns the current local timestamp.
   *
   * @static static
   * @access public
   * @return int
   */
  function localTimestamp()
    {
    return time();
    }


  /**
   * Returns the current UTC (Universal time) timestamp.
   *
   * @static static
   * @access public
   * @return int|bool
   */
  function universalTimestamp()
    {
    $params = TTime::temezone();
    $timestamp = time() - $params['timezone'] - $params['dstime'];
    if ($timestamp < 0 || $timestamp > 2147483647)
      return false;
    return $timestamp;
    }

  }

?>
 

tony2001

TeaM PHPClub
>PHP 4.0 вместе с Апачи вылетает в трубу под Microsoft Windows.
>Каковы будут коментарии и замечания?

комментарий только один: PHP4 мёртв и достаточно давно.
пора уже перестать заниматься некрофилией и найти что-то посвежее.
 

mira

Новичок
Когда клиент-некрофил заказывает сайт, ему по-барабану какой php стоит на его клиентском-некрофильском хостинге. Только не надо говорить - посылай некрофилов на ... Иногда у них больше денег...

А вообще я заметил(а), что на этом форуме никто не отвечает по существу. Спрашиваю про одно - коментарии про все что угодно, кроме темы сообщения! И так во всех топиках!
 

Фанат

oncle terrible
Команда форума
Просто точка зрения на существо вопроса у всех разная. Не надо считать свою единственно правильной.
 

mira

Новичок
Ф а н а т - твой пост только подтверждает мое высказывание!
 

Фанат

oncle terrible
Команда форума
не, ну серьезно. пыху версии 4.0 уже лет 7 наверное.
я уверен, что он вообще нигде не стоит. поскольку 4.0 ставили только энтузиасты, которые ставят все новое. у которых сейчас стоит 5 последней версии.

А осторожные начали переходить на 4 начиная где-то с 4.2
Какой смысл писать проверяльшик параметров для таймстампа (да еще и такой громоздкий), если есть стопроцентная гарантия, что он никогда не понадобится?

у 4ю0 есть аного гораздо более худших недостатков, чем глюки с таймстампом. и логичнее было бы перстаивть версию (тем более - под винду), чем клепать какие-то непонятные воркэраунды.

И уж выклыдывать на форуме программистов совсем смешно. Нико здесь с этой версией не работает.
 

mira

Новичок
Только что проверил PHP5 под Windows. Сыпит нотасами, при некоторых датах (в том числе и на отрицательных)!!!

Пишем контроль панель, которая должна работать на разных операционках одинаково.

Для этого сужаем диапазон валидных дат
1970.01.01 00:00:00 - 2038.01.19 03:14:07
которые не бросают ошибки на разных операционках.

Класс создает одинаковый интерфейс ошибок на разных операционках. PHP4 и PHP5 функции - нет!!!

Что по вашему смешного не пойму!
 

mira

Новичок
Класс решает проблему нулевого таймстампа на серверах расположенных в положительной временной зоне...
Например: если у вас сервер Microsoft Windows и он расположен в Москве (TimeZone +3), то функции PHP не смогут обрабатывать дату с таймстампом = 0 UTC (соответствущий дате 1970.01.01 00:00:00 UTC). Кроме того вы не сможете поддерживать даты в диапазоне скажем - 1970.01.01 00:00:00 UTC - 1970.01.01 03:00:00 UTC средствами PHP-функций на сервере с временой зоной +3.
Данный класс решает эту проблему!
 

mira

Новичок
echo date('Y', -1);

Выдает предупреждение:

Warning: date(): Windows does not support dates prior to midnight (00:00:00), January 1, 1970

На Windows на сервере с временной зоной +3...
Таймстамп (-1) соответствует 23:59:59, December 31, 1969 LOCAL

Проблемма в том, что я не могу обработать дату 1970.01.01 00:00:00 UTC, так как PHP во всех своих функциях учитывает сдвиг временной зоны.

Речь идет о всемирном времени, а не о локальном времени.

Я не могу поддерживать даты в диапазоне 1970.01.01 00:00:00 UTC - 1970.01.01 03:00:00 UTC средствами PHP-функций на сервере с положительной временной зоной +3.

Хотя диапазон 1970.01.01 00:00:00 LOCALTIME - 1970.01.01 03:00:00 LOCALTIME - работать будет!
 

Фанат

oncle terrible
Команда форума
PHP:
error_reporting(E_ALL);
error_reporting(E_ALL);
echo phpversion();
echo "<br>";
echo date_default_timezone_get();
echo "<br>";
echo date("Y",-1);[code]5.1.1
Europe/Moscow
1970[/code]
что я делаю не так?

[size=1][i]-~{}~ 12.10.07  12:58:[/i][/size]

[quote]Я не могу поддерживать даты в диапазоне 1970.01.01 00:00:00 UTC - 1970.01.01 03:00:00 UTC средствами PHP-функций на сервере с положительной временной зоной +3. [/QUOTE]
Ну, это твои проблемы.
Все остальные-то могут, с помощью элементанных настроек.
 

mira

Новичок
Элементарные настройки на хостинге где админом работаю не я!

Проблема в том, что мне нужно хранить всемирные времена, а не локальные!

Очень сомневаюсь что это ответ из под Windows...
 

Фанат

oncle terrible
Команда форума
это ответ из-под виндоус.
чтобы хранить "всемирные времена", достаточно сделать настройки в самом скрипте.
восклицательные знаки здесь совсем лишние.
 

Фанат

oncle terrible
Команда форума
5.1.1
Europe/Moscow
Thursday 01st 1970f January 1970 02:59:59 AM

а можно спросить, какие именно нотисы выдает при неоторых датах?
 

mira

Новичок
Извиняюсь, выдает не Нотисы а Ворнинги!
Warning: ... : Windows does not support dates ...

Какой виндовс?
 

Фанат

oncle terrible
Команда форума
XP.
Можно ПОЛНЫЙ ТЕКСТ сообщения об ошибке, а не какой-то огрызок, из которого ничего непонятно?
 
Сверху