<?php  if (!defined('BASEPATH')) { exit('No direct script access allowed'); }
/**
 * CodeIgniter helper
 *
 * @category CodeIgniter
 * @license /_licenses/untermStrich/agb_normal.pdf
 * @author Christian Koller
 * @copyright 2009 untermStrich
 * @package helpers
 * @version $Id$
 */

if ( ! function_exists('datetime_diff')) {
    /**
     * Vergleicht zwei Datumswerte und gibt die Differenz in Sekunden zurück.
     * 
     * @param   DateTime|UsBasicDateTime  $date1  Das erste Datum
     * @param   DateTime|UsBasicDateTime  $date2  Das zweite Datum
     * @return  int
     */
    function datetime_diff($date1, $date2)
    {
        if (is_null($date1) || (method_exists($date1, 'is_null') && $date1->is_null())) {
            return 0;
        }
        if (is_null($date2) || (method_exists($date2, 'is_null') && $date2->is_null())) {
            $date_to = new DateTime('now');
            return $date_to->format('U') - $date1->format('U');
        } else {
            return $date2->format('U') - $date1->format('U');
        }
    }
}

if ( ! function_exists('datetime_diff_minutes')) {
    /**
     * Compares the 2 date. Returns the difference in minutes between the 2 dates
     *
     * <ul>
     *  <li>If the first date is before the second - positive value</li>
     *  <li>If the first date is past the second date - negative value</li>
     * </ul>
     *
     * @param   object  $date1  The DateTime 1
     * @param   object  $date2  The DateTime 2
     * @return  integer
     *
     * @todo    We might want to change this into using ->diff as soon as PHP 5.3 is common
     */
    function datetime_diff_minutes(UsBasicDateTime $date1, UsBasicDateTime $date2)
    {
        return datetime_diff($date1, $date2)/60;
    }
}

if ( ! function_exists('datetime_diff_hours')) {
    /**
     * Vergleicht zwei Datumswerte und gibt die Differenz in Stunden zurück.
     *
     * @param   DateTime|UsBasicDateTime  $date1  Das erste Datum
     * @param   DateTime|UsBasicDateTime  $date2  Das zweite Datum
     * @return  float
     */
    function datetime_diff_hours($date1, $date2)
    {
        return datetime_diff($date1, $date2) / 3600;
    }
}

if ( ! function_exists('datetime_diff_days')) {
    /**
     * Compares the 2 date. Returns the difference in days between the 2 dates
     *
     * <ul>
     *  <li>If the first date is before the second - positive value</li>
     *  <li>If the first date is past the second date - negative value</li>
     * </ul>
     *
     * @param   object  $date1  The DateTime 1
     * @param   object  $date2  The DateTime 2
     * @return  integer
     *
     * @todo    We might want to change this into using ->diff as soon as PHP 5.3 is common
     */
    function datetime_diff_days(UsBasicDateTime $date1, UsBasicDateTime $date2)
    {
        return round(datetime_diff($date1, $date2)/86400);
    }
}


if ( ! function_exists('diff_to_hours')) {
    /**
     * Transforms seconds into a time value
     *
     * @param       float   $value  The time in seconds
     * @return      string  The time in 'D HH:MM::SS'
     */
    function diff_to_hours($value)
    {
        if ($value<0) return '';
        $m = (int)($value / 60);
        $s = $value % 60;
        $h = (int)($m / 60);
        $m = $m % 60;
        $d = (int)($h / 24);
        $h = $h % 24;
        return sprintf(
                '%s %s:%s:%s',
                ($d>0) ? $d : '',
                ($h<10) ? '0'.$h : $h,
                ($m<10) ? '0'.$m : $m,
                ($s<10) ? '0'.$s : $s
        );
    }
}


if ( ! function_exists('us_first_last_day_of_week')) {
    /**
     * Get first and last day of week
     *
     * @param   object  $day        Optional A day within the week
     * @return  object  A UsTimePeriod
     */
    function us_first_last_day_of_week(UsDate $day=null)
    {
        $reply = new stdClass();
        
        if ($day===null) {
            $day = new UsDate('now');
        }

        $reply = new UsTimePeriod(
                new UsDate('last Monday '.$day->mysqlday()),
                new UsDate('next Sunday '.$day->mysqlday())
        );

        if ( $day->format('N')==='1' ) {
            $reply->first = $day;
        } else if ( $day->format('N')==='7' ) {
            $reply->last = $day;
        }

        return $reply;
    }
}

if ( ! function_exists('us_first_last_day_of_month')) {
    /**
     * Get first and last day of month
     *
     * @param   object  $day        Optional A day within the month
     * @return  object  A UsTimePeriod
     */
    function us_first_last_day_of_month(UsBasicDateTime $day=null)
    {
        if ($day===null) {
            $day = new UsDate('now');
        }

        $first = new UsDate('first day of '.$day->mysqlday());
        $last = new UsDate('last day of '.$day->mysqlday());
        return new UsTimePeriod($first, $last);
    }
}

if ( ! function_exists('row_field_datetime')) {
    /**
     * Replaces the mysql string based date into UsDateTime and remove the string
     *
     * Checks if the field exists, before it starts working
     *
     * @param   object  &$result_object Result object
     * @param   string  $field          Name of the field (Without str)
     * @param   string  $fieldstr       Optional Name in the database query
     * @return  void
     */
    function row_field_datetime(&$result_object, $field, $fieldstr=null)
    {
        if ($fieldstr===null) $fieldstr = $field . 'str';
        if ( property_exists($result_object, $fieldstr) && !is_object($result_object->$fieldstr) ) {
            $result_object->$field = new UsDateTime($result_object->$fieldstr);
            if($fieldstr!=$field) unset($result_object->$fieldstr);
        }
    }
}


if ( ! function_exists('row_field_date')) {
    /**
     * Replaces the mysql string based date into UsDate and remove the string
     *
     * Checks if the field exists, before it starts working
     *
     * @param   object  &$result_object Result object
     * @param   string  $field          Name of the field (Without str)
     * @param   string  $fieldstr       Optional Name in the database query
     * @return  void
     */
    function row_field_date(&$result_object, $field, $fieldstr=null)
    {
        if ($fieldstr===null) $fieldstr = $field . 'str';
        if ( property_exists($result_object, $fieldstr) && !is_object($result_object->$fieldstr) ) {
            $result_object->$field = new UsDate($result_object->$fieldstr);
            if($fieldstr!=$field) unset($result_object->$fieldstr);
        }
    }
}


if ( ! function_exists('row_field_time')) {
    /**
     * Replaces the mysql string based date into UsTime and remove the string
     *
     * Checks if the field exists, if not it sets ''
     *
     * @param   object  &$result_object Result object
     * @param   string  $field          Name of the field (Without str)
     * @param   string  $fieldstr       Optional Name in the database query
     * @return  void
     */
    function row_field_time(&$result_object, $field, $fieldstr=null)
    {
        if ($fieldstr===null) $fieldstr = $field . 'str';
        if ( property_exists($result_object, $fieldstr) && !is_object($result_object->$fieldstr) ) {
            $result_object->$field = new UsTime($result_object->$fieldstr);
            if($fieldstr!=$field) unset($result_object->$fieldstr);
        }
    }
}

if ( ! function_exists('easter_days')) {
    /**
     * Get number of days after 21.03 on which easter falls
     * 
     * Accoding to https://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
     *
     * @param   integer $year   Year
     * @return  integer
     */
    function easter_days($year)
    {
        $a = $year % 19;
        $b = floor($year / 100);
        $c = $year % 100;
        $d = floor($b / 4);
        $e = $b % 4;
        $f = floor(($b + 8) / 25);
        $g = floor(($b - $f + 1) / 3);
        $h = (19*$a + $b - $d - $g + 15) % 30;
        $i = floor($c / 4);
        $k = $c % 4;
        $l = (32 + 2*$e + 2*$i - $h - $k) % 7;
        $m = floor(($a + 11*$h + 22*$l) / 451);
        
        $x = ($h + $l - 7*$m + 114);
        $month = floor($x / 31);
        $day = ($x % 31) + 1;

        #Return the difference between easter and 21.03
        $from = mktime(0, 0, 0, $month, $day, $year);
        $to = mktime(0, 0, 0, 3, 21, $year);
        return round( ($from-$to)/86400, 0);
    }
}

if ( ! function_exists('date_prev_months')) {
    /**
     * Get previous months
     * 
     * @param   UsBasicDateTime     &$date      Reference Date Time
     * @param   integer             $months     Months
     * @return  void
     */
    function date_prev_months(&$date, $months)
    {
        $first_last = us_first_last_day_of_month($date);
        
        if ($first_last->first->mysqlday()===$date->mysqlday()) {
            for ($index = 0; $index<$months; $index++) {
                $date->modify('first day of previous month');
            }
            return;

        } elseif ($first_last->last->mysqlday()===$date->mysqlday()) {

            for ($index = 0; $index<$months; $index++) {
                $date->modify('last day of previous month');
            }
            return;
        }
        
        if ($months===12) {
            $date->modify('-1 year');
        } else {
            $date->modify('-'.intval($months).' month');
        }
    }
}

if ( ! function_exists('date_to_zulu')) {
    /**
     * Get date as Ymd\THis in Zulu/UTC
     * 
     * @param   UsBasicDateTime     $date       Date Time
     * @return  string
     */
    function date_to_zulu(UsDateTime $date): string {
        return (clone $date)
            ->setTimezone(new DateTimeZone('UTC'))
            ->format('Ymd\THis\Z');
    }
}

/* End of file us_date_helper.php */
