<?php
/* MT4Analysis - Date and time functions.
   Copyright (C) 2010, Future Lab.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, get a copy via the Internet at
   http://gnu.org/copyleft/gpl.html or write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   MA 02111-1307 USA

   You can contact the author via email at rsmereka@future-lab.com

   Original version. Aug/2010, Rick Smereka */

define('DATIME_SEC_DAY', 86400);
define('DATIME_SEC_HOUR', 3600);

function tsentence($span)
{
   /* Based on the array 'span' (returned by either 'tspan' or
      'tspan_estimate', return an English time span sentence 
      (eg: 2 years, 3 months, 14 days, 11 hours, 1 minute, 45 seconds). 
      Returns the sentence string upon success, an empty string otherwise. */
   $ret = '';

   if ($span['year'] > 0)
      {
      $ret = $span['year'] . ' year';

      if ($span['year'] > 1)
         $ret .= 's';
      }

   if ($span['month'] > 0)
      {
      $ret .= ' ' . $span['month'] . ' month';

      if ($span['month'] > 1)
         $ret .= 's';
      }

   if ($span['day'] > 0)
      {
      $ret .= ' ' . $span['day'] . ' day';
    
      if ($span['day'] > 1)
         $ret .= 's';
      }

   if ($span['hour'] > 0)
      {
      $ret .= ' ' . $span['hour'] . ' hour';

      if ($span['hour'] > 1)
         $ret .= 's';
      }

   if ($span['minute'] > 0)
      {
      $ret .= ' ' . $span['minute'] . ' minute';

      if ($span['minute'] > 1)
         $ret .= 's';
      }

   if ($span['second'] > 0)
      {
      $ret .= ' ' . $span['second'] . ' second';

      if ($span['second'] > 1)
         $ret .= 's';
      }

   return(trim($ret));
}

function tspan($sdate, $edate)
{
   /* Determine the time span between two dates/times. 'sdate' and 'edate'
      must be acceptable to 'date_parse'. Returns an associative array with
      the elements 'year', 'month', 'day', 'hour', 'minute', 'second' and
      'seconds' (number of elapsed seconds) loaded with the time span.  In
      addition 'ryear', 'rmonth', 'rday', 'rhour', 'rminute' and 'rsecond'
      are loaded with the roving date. Function works by obtaining the
      number of seconds difference in the two dates and by loading the
      roving date array with the start date. Each date/time component
      is subtraced from the number of seconds while the roving date is
      incremented. The roving date is used to lookup the current date and
      determine whether it is a leap year and the number of days in the
      month. If this function is working properly, the roving date on exit
      should be equal to the end date. Returns 'false' on error. */
   $array_sdate = date_parse($sdate);
   $array_edate = date_parse($edate);
   /* echo "*** array_sdate<BR />\n";
   print_r($array_sdate);
   echo "*** array_edate<BR />\n";
   print_r($array_edate); */

   if ($array_sdate['error_count'] > 0)
      {
      /* echo "*** date sdate invalid<BR />\n";
      printr($array_sdate['errors']); */
      return(false);
      }

   if ($array_edate['error_count'] > 0)
      {
      /* echo "*** date edate invalid<BR />\n";
      printr($array_edate['errors']); */
      return(false);
      }

   $ustamp_sdate = strtotime($sdate);
   $ustamp_edate = strtotime($edate);
   $array_rdate = $array_sdate;       // roving date
   $array_out['year'] = $array_out['month'] = $array_out['day'] = 
                        $array_out['hour'] = $array_out['minute'] =
                        $array_out['second'] = $array_out['seconds'] =
                        $array_out['ryear'] = $array_out['rmonth'] =
                        $array_out['rday'] = $array_out['rhour'] =
                        $array_out['rminute'] = $array_out['rsecond'] = 0;
   $ustamp_dif = $ustamp_edate - $ustamp_sdate;
   $array_out['seconds'] = $ustamp_dif;
   /* echo "ustamp_sdate=$ustamp_sdate,ustamp_edate=$ustamp_edate<BR />\n";
   echo "ustamp_dif=$ustamp_dif<BR />\n"; */
   $roving_year = $array_rdate['year'];

   // calculate seconds in start year
   if (isleap($roving_year))
      $sec_year = 366 * DATIME_SEC_DAY;
   else
      $sec_year = 365 * DATIME_SEC_DAY;

   // echo "sec_year=$sec_year<BR />\n";

   // years
   while($ustamp_dif >= $sec_year)
      {
      // echo "seconds in year $roving_year are $sec_year<BR />\n";
      $ustamp_dif -= $sec_year;
      $roving_year++;
      $array_out['year']++;

      if (isleap($roving_year))
         $sec_year = 366 * DATIME_SEC_DAY;
      else
         $sec_year = 365 * DATIME_SEC_DAY;
      }

   $array_rdate['year'] = $roving_year;
   $roving_month = $array_rdate['month'];
   $sec_month = days_in_month($array_rdate['year'], $roving_month) * 
                DATIME_SEC_DAY;
   
   // months
   while($ustamp_dif >= $sec_month)
      {
      // echo "seconds in month $roving_month are $sec_month<BR />\n";
      $ustamp_dif -= $sec_month;
      $roving_month++;
      $array_out['month']++;

      if ($roving_month > 12)
         {
         $roving_month = 1;
         $array_rdate['year']++;
         }

      $sec_month = days_in_month($array_rdate['year'], $roving_month) *
                                 DATIME_SEC_DAY;
      }

   $array_rdate['month'] = $roving_month;
   $roving_day = $array_rdate['day'];
   $sec_day = DATIME_SEC_DAY;

   // days
   while($ustamp_dif >= $sec_day)
      {
      // echo "seconds in day $roving_day are $sec_day<BR />\n";
      $ustamp_dif -= $sec_day;
      $roving_day++;
      $array_out['day']++;
      $days = days_in_month($array_rdate['year'], $array_rdate['month']);

      if ($roving_day > $days)
         {
         $array_rdate['month']++;
         $roving_day = 1;

         if ($array_rdate['month'] > 12)
            {
            $array_rdate['month'] = 1;
            $array_rdate['year']++;
            }
         }
      }

   $array_rdate['day'] = $roving_day;
   $roving_hour = $array_rdate['hour'];
   $sec_hour = DATIME_SEC_HOUR;

   // hours
   while($ustamp_dif >= $sec_hour)
      {
      // echo "seconds in hour $roving_hour are $sec_hour<BR />\n";
      $ustamp_dif -= $sec_hour;
      $roving_hour++;
      $array_out['hour']++;

      if ($roving_hour > 23)
         {
         $roving_hour = 0;
         $array_rdate['day']++;
         $days = days_in_month($array_rdate['year'], $array_rdate['month']);

         if ($array_rdate['day'] > $days)
            {
            $array_rdate['month']++;
            $array_rdate['day'] = 1;

            if ($array_rdate['month'] > 12)
               {
               $array_rdate['month'] = 1;
               $array_rdate['year']++;
               }
            }
         }
      }
   
   $array_rdate['hour'] = $roving_hour;
   $roving_minute = $array_rdate['minute'];
   $sec_minute = 60;

   // minutes
   while($ustamp_dif >= $sec_minute)
      {
      // echo "seconds in minute $roving_minute are $sec_minute<BR />\n";
      $ustamp_dif -= $sec_minute;
      $roving_minute++;
      $array_out['minute']++;

      if ($roving_minute > 59)
         {
         $roving_minute = 0;
         $array_rdate['hour']++;

         if ($array_rdate['hour'] > 23)
            {
            $array_rdate['hour'] = 0;
            $array_rdate['day']++;
            }

         $days = days_in_month($array_rdate['year'], $array_rdate['month']);

         if ($array_rdate['day'] > $days)
            {
            $array_rdate['day'] = 1;
            $array_rdate['month']++;
            }

         if ($array_rdate['month'] > 12)
            {
            $array_rdate['month'] = 1;
            $array_rdate['year']++;
            }
         }
      }

   $array_rdate['minute'] = $roving_minute;
   $roving_second = $array_rdate['second'];

   // seconds
   while($ustamp_dif >= 1)
      {
       //echo "second $roving_second<BR />\n";
      $ustamp_dif--;
      $roving_second++;
      $array_out['second']++;

      if ($roving_second > 59)
         {
         $roving_second = 0;
         $array_rdate['minute']++;

         if ($array_rdate['minute'] > 59)
            {
            $array_rdate['minute'] = 0;
            $array_rdate['hour']++;
            }

         if ($array_rdate['hour'] > 23)
            {
            $array_rdate['hour'] = 0;
            $array_rdate['day']++;
            }

         $days = days_in_month($array_rdate['year'], $array_rdate['month']);

         if ($array_rdate['day'] > $days)
            {
            $array_rdate['day'] = 1;
            $array_rdate['month']++;
            }

         if ($array_rdate['month'] > 12)
            {
            $array_rdate['month'] = 1;
            $array_rdate['year']++;
            }
         }
      }

   $array_rdate['second'] = $roving_second;
   $array_out['ryear'] = $array_rdate['year'];
   $array_out['rmonth'] = $array_rdate['month'];
   $array_out['rday'] = $array_rdate['day'];
   $array_out['rhour'] = $array_rdate['hour'];
   $array_out['rminute'] = $array_rdate['minute'];
   $array_out['rsecond'] = $array_rdate['second'];
   return($array_out);
}

function tspan_estimate($usd)
{
   /* Estimate the time span based on the difference between two Unix
      timestamps ('usd'). Returns an associative array with
      the elements 'year', 'month', 'day', 'hour', 'minute', and 'second'
      loaded with the time span. This function is designed to give a rough
      estimate of the time span involved as there is no access to the start
      and end dates. */
   $ustamp_dif = $usd;
   $array_out['year'] = $array_out['month'] = $array_out['day'] = 
                        $array_out['hour'] = $array_out['minute'] =
                        $array_out['second'] = 0;

   // calculate seconds in average year
   $sec_year = 365 * DATIME_SEC_DAY;

   // years
   while($ustamp_dif >= $sec_year)
      {
      $ustamp_dif -= $sec_year;
      $array_out['year']++;
      }

   // calculate seconds in average month (based on 30 days)
   $sec_month = 30 * DATIME_SEC_DAY;
   
   // months
   while($ustamp_dif >= $sec_month)
      {
      $ustamp_dif -= $sec_month;
      $array_out['month']++;
      }

   $sec_day = DATIME_SEC_DAY;

   // days
   while($ustamp_dif >= $sec_day)
      {
      $ustamp_dif -= $sec_day;
      $array_out['day']++;
      }

   $sec_hour = DATIME_SEC_HOUR;

   // hours
   while($ustamp_dif >= $sec_hour)
      {
      $ustamp_dif -= $sec_hour;
      $array_out['hour']++;
      }
   
   $sec_minute = 60;

   while($ustamp_dif >= $sec_minute)
      {
      $ustamp_dif -= $sec_minute;
      $array_out['minute']++;
      }

   while($ustamp_dif >= 1)
      {
      $ustamp_dif--;
      $array_out['second']++;
      }

   return($array_out);
}

function days_in_month($year, $month)
{
   /* Determine the number of days in a month taking into account
      leap years. Returns the number of days in 'month'
      upon success, zero otherwise. */

   $numdays = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
   $leap = 0;
   
   if ($month < 1 || $month > 12)
      return(0);

   $leap = isleap($year);

   if ($month == 2 && $leap)
      return(29);

   return($numdays[$month]);
}

function isleap($year)
{
   /* Determine whether the 'year' is a leap year. Function returns
      'TRUE' if the 'year' is a leap year, 'FALSE' otherwise. */

   return(($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
}
?>
