DIR : /home/kozerus/public_html/dgs/include/time_functions.php

/home/kozerus/public_html/dgs/include

<?php
/*
Dragon Go Server
Copyright (C) 2001-  Erik Ouchterlony, Rod Ival, Jens-Uwe Gaspar

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

$TranslateGroups[] = "Common";

require_once 'include/globals.php';
require_once 'include/cache_clock.php';


define('BYOTYPE_JAPANESE', 'JAP');
define('BYOTYPE_CANADIAN', 'CAN');
define('BYOTYPE_FISCHER',  'FIS');
define('REGEX_BYOTYPES', '('.BYOTYPE_JAPANESE.'|'.BYOTYPE_CANADIAN.'|'.BYOTYPE_FISCHER.')');


function getmicrotime()
{
   return microtime(/*float*/true);
}

function unix_timestamp($date)
{
   $pattern = "/(19|20)(\d{2})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})/";
   $m = preg_match ($pattern, $date, $matches);

   if (empty($date) || $date == "0000-00-00" || !$m)
      return NULL;

   list($whole, $y1, $y2, $month, $day, $hour, $minute, $second) = $matches;
   return mktime($hour,$minute,$second,$month,$day,$y1.$y2);
}


/*! \brief Returns true, if it's weekend (Sat/Sun) for UTC-timezone. */
function is_weekend( $timestamp=null )
{
   global $NOW;
   $day_of_week = gmdate('w', (is_null($timestamp) ? $NOW : $timestamp));
   return ( $day_of_week == 6 || $day_of_week == 0 ); // Sat | Sun
}

/*! Returns true, if given clock-id is within non-ticking weekend-clock. */
function is_weekend_clock_stopped( $clock_id, $timestamp=null )
{
   if ( $clock_id != GAME_WEEKEND_CLOCK ) // game-setting has clock running every day of the week
      $clock_stopped = false; // independent from weekend
   else // game-setting has clock running only on Mo-Fr
      $clock_stopped = is_weekend($timestamp);

   return $clock_stopped;
}

/*!
 * Returns game-clock to use for Games.ClockUsed depending on given args.
 * \param $weekendclock Y|N, e.g. from Games.WeekendClock
 * \param $on_vacation boolean if user is on vacation
 */
function get_game_clock( $weekendclock, $on_vacation=false )
{
   if ($on_vacation)
      return VACATION_CLOCK;
   else
      return ( $weekendclock === 'Y' ) ? GAME_CLOCK : GAME_WEEKEND_CLOCK;
}

function get_clock_ticks( $dbgmsg, $clock_used, $use_cache=true )
{
   $cache_clock = ClockCache::get_instance();
   return $cache_clock->load_clock_ticks( $dbgmsg.'.get_clock_ticks', $clock_used, $use_cache );
}

function ticks_to_hours($ticks)
{
   //returns the greatest non-negative integer within [0 , $ticks/TICK_FREQUENCY[
   return ( $ticks > TICK_FREQUENCY ) ? floor(($ticks-1) / TICK_FREQUENCY) : 0;
}

function time_remaining( $hours, &$main, &$byotime, &$byoper,
      $startmaintime, $byotype, $startbyotime, $startbyoper, $has_moved)
{
   $elapsed = $hours;

   if ( $main > $elapsed ) // still have main time left
   {
      $main -= $elapsed;

      // add extra-time on move for Fischer-time
      if ( $has_moved && $byotype == 'FIS' )
      {
         // not capping main-time after adding time if it exceeds starting-main-time (cap)
         // NOTE: avoiding complicated checks for add-time feature
         if ( $main < $startmaintime )
            $main = min($startmaintime, $main + $startbyotime);
      }

      return;
   }

   if ( $main > 0 )
      $elapsed -= $main;
   $main = 0;

   switch ( (string)$byotype )
   {
      case BYOTYPE_FISCHER:
         $byotime = $byoper = 0;  // time is up
         break;

      case BYOTYPE_JAPANESE:
      {
         if ( $startbyotime <= 0 )
         {
            $byotime = $byoper = 0; // no byo-yomi, time is up
            break;
         }

         if ( $byoper < 0 ) // entering byo-yomi
         {
            $byotime = $startbyotime;
            $byoper = $startbyoper-1;
         }

         /***
          * with B=$byotime, P=$byoper, S=$startbyotime, E=$elapsed
          *  and b=new byotime, p=new byoper
          * we have:
          *  A = B + P*S   //old amount of time (0 < B <= S)
          *  a = b + p*S   //new amount of time (0 < b <= S)
          *  a = A - E
          * then:
          *  a = A - E = B + P*S - E
          *  p = (a - b)/S = (B + P*S - E - b)/S
          * p must be big enough to keep (0 < b <= S)
          *  p = ceil((B + P*S - E)/S) -1 = ceil((B - E)/S) + P -1
          *  d = P-p = -ceil((B - E)/S) +1 = floor((E - B)/S) +1
          *  b = a - p*S = B + P*S - E - p*S = B - E + d*S
          * finally:
          *  d = floor((S + E - B)/S)
          *  $byoper-= d
          *  $byotime-= E - d*S
          * because E and (S-B) are positive integers, the (int) cast
          *  (which rounds towards zero) may be used instead of floor()
          ***/
         $deltaper = (int)(($startbyotime + $elapsed - $byotime)/$startbyotime);
         $byoper -= $deltaper;

         if ( $byoper < 0 )
            $byotime = $byoper = 0;  // time is up
         else if ( $has_moved )
            $byotime = $startbyotime;
         else
            $byotime-= $elapsed - $deltaper*$startbyotime;
         break;
      }//case BYOTYPE_JAPANESE

      case BYOTYPE_CANADIAN:
      {
         if ( $startbyoper <= 0 )
         {
            $byotime = $byoper = 0; // no byo-yomi, time is up
            break;
         }

         if ( $byoper < 0 ) // entering byo-yomi
         {
            $byotime = $startbyotime;
            $byoper = $startbyoper;
         }

         $byotime -= $elapsed;

         if ( $byotime <= 0 )
            $byotime = $byoper = 0;  // time is up
         else if ( $has_moved )
         {
            $byoper--; // byo stones
            if ( $byoper <= 0 ) // get new stones
            {
               $byotime = $startbyotime;
               $byoper = $startbyoper;
            }
         }
         break;
      }//case BYOTYPE_CANADIAN
   }
}//time_remaining

// remaining-time calculus aggregating remaining-time into one value of hours
// Ref: http://www.dragongoserver.net/forum/read.php?forum=4&thread=5728#5743
// - Fischer:   M main-time + T extra-time            -> M
// - Japanese:  M main-time + N * T extra-time        -> M + remainingN * T
// - Canadian:  M main-time + T extra-time / N stones -> M + currT / N
function time_remaining_value( $byotype, $startByotime, $startByoperiods, $currMaintime, $currByotime, $currByoperiods )
{
   $result = 0;

   switch ( (string)$byotype )
   {
      case BYOTYPE_FISCHER:
         $result = ($currMaintime > 0) ? $currMaintime : 0;
         break;

      case BYOTYPE_JAPANESE:
         // IMPORTANT NOTE: need to handle add-time properly, see also specs/time.txt !!
         //   byo-yomi partly reset on add-time needs special handling
         if ( $currMaintime > 0 ) // not in byo-yomi yet
         {
            $result = $currMaintime;
            if ( $currByoperiods > 0 ) // can happen after add-time (only for JAP-time)
               $result += $currByoperiods * $startByotime; // part byo-yomi reset
            elseif ( $startByotime > 0 ) // non-absolute
               $result += $startByoperiods * $startByotime;
         }
         else
         {// in byo-yomi
            $result = $currByotime;
            if ( $startByoperiods > 0 && $startByotime > 0 )
               $result += $currByoperiods * $startByotime;
         }
         break;

      case BYOTYPE_CANADIAN:
         // IMPORTANT NOTE: need to handle add-time properly, see also specs/time.txt !!
         //    byo-yomi fully resetted on add-time, so no special handling needed
         if ( $currMaintime > 0 ) // not in byo-yomi yet
         {
            $result = $currMaintime;
            if ( $startByoperiods > 0 ) // non-absolute
               $result += $startByotime / $startByoperiods;
         }
         else
         {// in byo-yomi
            if ( $startByoperiods > 0 && $currByoperiods > 0 ) // non-absolute
               $result = $currByotime / $currByoperiods;
            else
               $result = 0;
         }
         break;
   }
   return $result;
}//time_remaining_value

// returns CSS-class if hours within warning-level for remaining-time
function get_time_remaining_warning_class( $hours )
{
   if ( $hours <= 3 * HOURS_PER_DAY )
      return 'RemTimeWarn1';
   elseif ( $hours <= 7 * HOURS_PER_DAY )
      return 'RemTimeWarn2';
   else
      return '';
}

/*!
 * \brief Builds time-remaining info.
 * \param $grow = Games-row with (White|Black)_(Maintime|Byotime|Byoperiods),
 *              X_Ticks, LastTicks, Maintime, Byotype, Byotime, Byoperiods
 * \param $color BLACK | WHITE - for which player of game to calculate remaining time
 * \param $is_to_move true if color-user is to move (taking current ticks into account)
 * \return array( attbs => CSS-arr, text => remaining-time-str )
 */
function build_time_remaining( array $grow, $color, $is_to_move, $timefmt = null )
{
   $prefix_col = ($color == BLACK) ? 'Black' : 'White';
   $userMaintime   = $grow[$prefix_col.'_Maintime'];
   $userByotime    = $grow[$prefix_col.'_Byotime'];
   $userByoperiods = $grow[$prefix_col.'_Byoperiods'];
   if ( is_null($timefmt) )
      $timefmt = TIMEFMT_ADDTYPE | TIMEFMT_ZERO;

   // no Ticks (vacation) == 0 => lead to 0 elapsed hours
   $elapsed_hours = ( $is_to_move ) ? ticks_to_hours(@$grow['X_Ticks'] - @$grow['LastTicks']) : 0;

   time_remaining($elapsed_hours, $userMaintime, $userByotime, $userByoperiods,
      $grow['Maintime'], $grow['Byotype'], $grow['Byotime'], $grow['Byoperiods'], false);

   $hours_remtime = time_remaining_value( $grow['Byotype'], $grow['Byotime'], $grow['Byoperiods'],
      $userMaintime, $userByotime, $userByoperiods );
   $class_remtime = get_time_remaining_warning_class( $hours_remtime );

   $rem_time = TimeFormat::echo_time_remaining( $userMaintime, $grow['Byotype'], $userByotime,
      $userByoperiods, $grow['Byotime'], $grow['Byoperiods'], $timefmt );

   return array(
         'attbs' => array( 'class' => $class_remtime ),
         'text'  => $rem_time,
      );
}//build_time_remaining

/*!
 * \brief Returns "absolute" time in ticks aligned with Clock[ID=CLOCK_TIMELEFT].
 * \param $hours_left hours_left is not precise but following the calculus of time_remaining_value()
 *
 * \note used for time-remaining ordering, weekend-clocks not supported
 * \see for full specs and pitfalls, see 'TimeOutDate/ClockUsed/LastTicks'-field in 'specs/db/table-Games.txt'
 */
function time_left_ticksdate( $hours_left, $curr_ticks=-1 )
{
   if ( $curr_ticks < 0 )
      $curr_ticks = get_clock_ticks( 'time_left_ticksdate', CLOCK_TIMELEFT );

   $ticks_date = $curr_ticks + round( $hours_left * TICK_FREQUENCY );
   return $ticks_date;
}

// convert full days to ticks
function timeleft_days_to_ticks( $days )
{
   return HOURS_PER_DAY * $days * TICK_FREQUENCY;
}


// $unit: hours, months, or else days
function time_convert_to_hours($time, $unit)
{
   $time = (int)$time;
   if ( $unit != 'hours' )
      $time *= HOURS_PER_DAY;
   if ( $unit == 'months' )
      $time *= 30;
   return $time;
} //time_convert_to_hours

// $unit : hours | days | months
function time_convert_to_longer_unit( &$time, &$unit )
{
   if ( $unit == 'hours' && $time % HOURS_PER_DAY == 0 )
   {
      $unit = 'days';
      $time /= HOURS_PER_DAY;
   }

   if ( $unit == 'days' && $time % 30 == 0 )
   {
      $unit = 'months';
      $time /= 30;
   }
}//time_convert_to_longer_unit



define('TIMEFMT_ENGL',     0x0001 ); // ignore users-language (keep english)
define('TIMEFMT_SHORT',    0x0002 ); // long-text <-> short-text form
define('TIMEFMT_HTMLSPC',  0x0004 ); // whitespace separator: plain space <-> HTML &nbsp;
define('TIMEFMT_ADDTYPE',  0x0008 ); // omit byo-type <-> include byo-type
define('TIMEFMT_NO_EXTRA', 0x0010 ); // include extra-time <-> omit extra-time (byo-yomi)
define('TIMEFMT_ZERO',     0x0020 ); // use zero time <-> return special-zero-value on zero
define('TIMEFMT_ADD_HOUR', 0x0040 ); // always add hours (even if 0h)
define('TIMEFMT_QUICK',    0x0080 ); // time-format for quick-suite (also see specs/quick_suite.txt)
define('TIMEFMT_HOUR2',    0x0100 ); // format hours with 2 chars (leading spaces)

/*!
 * \brief Static helper class to format Dragon time.
 */
class TimeFormat
{

   // "7d" (short), "7 days" (long)
   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC
   public static function echo_day( $days, $fmtflags=0 )
   {
      if ( ($fmtflags & TIMEFMT_SHORT) && ($fmtflags & TIMEFMT_ENGL) )
         return $days . 'd';

      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';
      $absdays = abs($days);

      $str = $days;
      if ( $fmtflags & TIMEFMT_SHORT )
         $str .= ( $absdays > 0 && $absdays <= 1 ) ? $T_('day#short') : $T_('days#short');
      else
         $str .= ' ' . ( ($absdays > 0 && $absdays <= 1) ? $T_('day') : $T_('days') );

      return self::_replace_space($str, $fmtflags);
   }//echo_day

   // "3h" (short), "3 hours" (long)
   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_HOUR2
   public static function echo_hour( $hours, $fmtflags=0 )
   {
      $prefix = (($fmtflags & TIMEFMT_HOUR2) && $hours < 10) ? (($fmtflags & TIMEFMT_HTMLSPC) ? MINI_SPACING : ' ') : '';
      if ( ($fmtflags & TIMEFMT_SHORT) && ($fmtflags & TIMEFMT_ENGL) )
         return $prefix . $hours . 'h';

      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';
      $abshours = abs($hours);

      $str = $prefix . $hours;
      if ( $fmtflags & TIMEFMT_SHORT )
         $str .= ( $abshours > 0 && $abshours <= 1 ) ? $T_('hour#short') : $T_('hours#short');
      else
         $str .= ' ' . ( ($abshours > 0 && $abshours <= 1) ? $T_('hour') : $T_('hours') );

      return self::_replace_space($str, $fmtflags);
   }//echo_hour

   // "5d 7h" (short), "5 days and 7 hours" (long)
   // 0 -> zero_value
   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_ZERO
   public static function _echo_time( $hours, $hours_per_day, $fmtflags=0, $zero_value=NO_VALUE )
   {
      if ( $hours <= 0 )
         return ($fmtflags & TIMEFMT_ZERO) ? self::echo_hour(0, $fmtflags) : $zero_value;

      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';

      $h = $hours % $hours_per_day;
      $days = ($hours-$h) / $hours_per_day;
      $str = ( $days > 0 ) ? self::echo_day( $days, $fmtflags ) : '';

      if ( $h > 0 || ($fmtflags & TIMEFMT_ADD_HOUR) ) //or $str == '' )
      {
         if ( $str > '' )
         {
            $str .= ' ';
            if ( !($fmtflags & TIMEFMT_SHORT) )
               $str .= $T_('and') . ' ';
         }

         $str .= self::echo_hour( $h, $fmtflags );
      }

      return self::_replace_space($str,$fmtflags);
   }//_echo_time

   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_ZERO
   public static function echo_time( $hours, $fmtflags=0, $zero_value=NO_VALUE )
   {
      return self::_echo_time( $hours, HOURS_PER_DAY, $fmtflags, $zero_value );
   }

   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_ZERO
   public static function echo_time_diff( $now, $time, $hours_per_day, $fmtflags=0, $zero_value=NO_VALUE )
   {
      if ( $time > 0 )
      {
         $hours_diff = round( ($now - $time) / SECS_PER_HOUR );
         return self::_echo_time( $hours_diff, $hours_per_day, $fmtflags, $zero_value );
      }
      else
         return '';
   }

   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_ZERO, TIMEFMT_QUICK
   public static function echo_onvacation( $days, $fmtflags=0, $zero_value=NO_VALUE )
   {
      $hours = round($days*HOURS_PER_DAY);
      if ( !($fmtflags & TIMEFMT_QUICK) && ( $hours > 0 || ($fmtflags & TIMEFMT_ZERO) ) )
         $fmt = ($fmtflags & TIMEFMT_ENGL) ? '%s left' : T_('%s left#vacation');
      else
         $fmt = '%s';
      $str = sprintf( $fmt, self::_echo_time( $hours, HOURS_PER_DAY, $fmtflags, $zero_value ) );
      return self::_replace_space($str,$fmtflags);
   }

   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT
   public static function echo_byotype( $byotype, $fmtflags=0 )
   {
      if ( $fmtflags & TIMEFMT_SHORT )
         return substr($byotype, 0, 1); // J, C, F

      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';
      switch ( (string)$byotype )
      {
         case BYOTYPE_JAPANESE:
            return $T_('Japanese byo-yomi');
         case BYOTYPE_CANADIAN:
            return $T_('Canadian byo-yomi');
         case BYOTYPE_FISCHER:
            return $T_('Fischer time');
      }

      return '';
   }//echo_byotype

   // "J: 7d 3h + 2d * 5" (short), "J: $maintime + $byotime per move and $byoper extra periods"
   // "C: 7d 3h + 9d / 3" (short), "C: $maintime + $byotime per NUMBER stones"
   // "F: 7d 3h + 2d"     (short), "F: $maintime + $byotime per move"
   // type, maintime or extra-time are optional
   // fmtflags: TIMEFMT_ENGL, TIMEFMT_SHORT, TIMEFMT_HTMLSPC, TIMEFMT_ZERO, TIMEFMT_ADDTYPE
   public static function echo_time_limit( $maintime, $byotype, $byotime, $byoper, $fmtflags=TIMEFMT_ADDTYPE )
   {
      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';
      $str = '';

      if ( $fmtflags & TIMEFMT_ADDTYPE )
         $str .= self::echo_byotype($byotype, $fmtflags) . ': ';

      if ( $maintime > 0 )
         $str .= self::echo_time($maintime, $fmtflags) . ' ';

      if ( $maintime <= 0 && $byotime <= 0 )
      {
         $str .= self::echo_hour(0, $fmtflags);
      }
      else if ( $byotype == BYOTYPE_FISCHER )
      {
         if ( $byotime > 0 )
         {
            if ( $fmtflags & TIMEFMT_SHORT )
               $str .= '+ ' . self::echo_time($byotime, $fmtflags);
            else
               $str .= sprintf( $T_('with %s extra per move'), self::echo_time($byotime, $fmtflags) );
         }//else: absolute-time
      }
      else // JAP|CAN
      {
         if ( $byotime <= 0 ) // absolute-time
         {
            if ( !($fmtflags & TIMEFMT_SHORT) )
               $str .= $T_('without byo-yomi');
         }
         else // has byo-time
         {
            if ( $maintime > 0 )
               $str .= '+ ';

            if ( $fmtflags & TIMEFMT_SHORT )
            {
               $str .= self::echo_time($byotime, $fmtflags);
               if ( $byotype == BYOTYPE_JAPANESE )
                  $str .= " * $byoper";
               else //if ( $byotype == BYOTYPE_CANADIAN )
                  $str .= " / $byoper";
            }
            else
            {
               if ( $byotype == BYOTYPE_JAPANESE )
                  $str .= sprintf( $T_('%s per move and %s extra periods'), self::echo_time($byotime, $fmtflags), $byoper );
               else //if ( $byotype == BYOTYPE_CANADIAN )
                  $str .= sprintf( $T_('%s per %s stones'), self::echo_time($byotime, $fmtflags), $byoper );
            }
         }
      }

      return self::_replace_space($str, $fmtflags);
   }//echo_time_limit


   // fmtflags: TIMEFMT_ENGL, TIMEFMT_HTMLSPC, TIMEFMT_ZERO, TIMEFMT_ADDTYPE, TIMEFMT_NO_EXTRA
   public static function echo_time_remaining( $maintime, $byotype, $byotime, $byoper, $startbyotime, $startbyoper, $fmtflags=null )
   {
      if ( is_null($fmtflags) )
         $fmtflags = TIMEFMT_ADDTYPE;
      $fmtflags |= TIMEFMT_SHORT; // default
      $T_= ($fmtflags & TIMEFMT_ENGL) ? 'fnop' : 'T_';
      $str = '';

      if ( $fmtflags & TIMEFMT_ADDTYPE )
         $str .= self::echo_byotype($byotype, $fmtflags) . ': ';

      // remaining main/byo-yomi-time
      $rem_time = $maintime;
      if ( $maintime <= 0 )
      {
         if ( $byotype == BYOTYPE_FISCHER || $byotime <= 0 ) // time is up
         {
            $str .= self::echo_time($maintime, $fmtflags | TIMEFMT_ZERO);
            return self::_replace_space($str, $fmtflags);
         }

         $rem_time = $byotime;
      }

      $str .= self::echo_time($rem_time, $fmtflags) . ' ';

      if ( $startbyotime <= 0 ) // absolute time
      {
         if ( !($fmtflags & TIMEFMT_NO_EXTRA) )
            $str .= '(-)';
         return self::_replace_space($str, $fmtflags);
      }

      // ignore invalid time-values (M=0, B>0); should not occur esp. after add-time
      if ( $byotype == BYOTYPE_CANADIAN && $maintime <= 0 && $byotime > 0 && $byoper > 0 )
         $str .= "/ $byoper ";

      // extra-time
      if ( !($fmtflags & TIMEFMT_NO_EXTRA) )
      {
         if ( $byotype == BYOTYPE_FISCHER )
            $str .= '(+ ' . self::echo_time($startbyotime, $fmtflags) . ')';
         else // JAP | CAN
         {
            if ( $byotype == BYOTYPE_CANADIAN )
               $rem_byoper = $startbyoper;
            else //if ( $byotype == BYOTYPE_JAPANESE )
               $rem_byoper = ( $byoper >= 0 ) ? $byoper : $startbyoper;

            $str2 = self::echo_time_limit( 0, $byotype, $startbyotime, $rem_byoper, $fmtflags & ~TIMEFMT_ADDTYPE );
            $str .= ( $maintime > 0 ) ? "(+ $str2)" : "($str2)";
         }
      }

      return self::_replace_space($str, $fmtflags);
   }//echo_time_remaining

   // \internal
   private static function _replace_space( $str, $opts )
   {
      if ( !($opts & TIMEFMT_QUICK) && ($opts & TIMEFMT_HTMLSPC) )
         return str_replace( ' ', '&nbsp;', trim($str) );
      else
         return trim($str);
   }

   /*!
    * \brief Returns number of hours parsed from "99d 99h" or "999" (hours); null on error.
    * \note Examples: "2d 3h 7h" = 2*24 + 3 + 7 hours, "7" = 7 hours
    */
   public static function parse_time_days_hours( $str )
   {
      $str = strtolower(trim($str));
      if ( (string)$str == '' )
         return 0;
      elseif ( is_numeric($str) && $str >= 0 )
         return (int)$str;

      $hours = 0;
      $parts = preg_split( "/\s+/", strtolower(trim($str)) );
      foreach ( $parts as $part )
      {
         unset($matches);
         if ( !preg_match("/^(\d+)(h|d)?$/", $part, $matches) )
            return NULL; // error
         if ( $matches[2] == 'd' )
            $hours += HOURS_PER_DAY * (int)$matches[1];
         elseif ( $matches[2] == 'h' || (string)$matches[2] == '' )
            $hours += (int)$matches[1];
      }
      return $hours;
   }//parse_time_days_hours

} //end 'TimeFormat'

?>
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer