Ticket #425: jduration.patch

File jduration.patch, 12.0 kB (added by flh, 11 months ago)

Proposition de patch avec tests unitaires

  • testapp/modules/jelix_tests/tests/utils.jduration.html_cli.php

    old new  
     1<?php 
     2/** 
     3* @package     testapp 
     4* @subpackage  jelix_tests module 
     5* @author      Florian Hatat 
     6* @copyright   2008 Florian Hatat 
     7* @link        http://www.jelix.org 
     8* @licence     GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html 
     9*/ 
     10 
     11class testjDuration extends UnitTestCase { 
     12    function testReportedBug(){ 
     13        // Get now date/time 
     14        $dtNow = new jDateTime(); 
     15        $dtNow->setFromString("2008-02-08 00:27:22", jDateTime::DB_DTFORMAT); 
     16 
     17        // Get expiration date 
     18        $expirationDate = "2008-02-12 00:00:00"; 
     19 
     20        // Create date time object from DB date 
     21        $dtExpirationDate = new jDateTime(); 
     22        $dtExpirationDate->setFromString($expirationDate, jDateTime::DB_DTFORMAT); 
     23 
     24        // Compute difference between these dates 
     25        try 
     26        { 
     27            $countdown = $dtNow->durationTo($dtExpirationDate); 
     28            $dtNow->add($countdown); 
     29            $this->assertEqual($dtNow, $dtExpirationDate); 
     30        } 
     31        catch (Exception $e) 
     32        { 
     33            $this->fail("Rejected duration construction"); 
     34        } 
     35    } 
     36 
     37    function testPositive(){ 
     38        $dur = new jDuration(20); 
     39        $dt = new jDateTime(2007, 12, 25, 15, 28, 17); 
     40        $dtExpected = new jDateTime(2007, 12, 25, 15, 28, 37); 
     41        $dt->add($dur); 
     42        $this->assertEqual($dt, $dtExpected); 
     43    } 
     44 
     45    function testRelative1(){ 
     46        $dur = new jDuration(array("month" => 1)); 
     47        $dt = new jDateTime(2007, 8, 14, 15, 28, 17); 
     48        $dtExpected = new jDateTime(2007, 9, 14, 15, 28, 17); 
     49        $dt->add($dur); 
     50        $this->assertEqual($dt, $dtExpected); 
     51    } 
     52 
     53    function testRelative2(){ 
     54        $dur = new jDuration(array("month" => 1)); 
     55        $dt = new jDateTime(2007, 1, 14, 15, 28, 17); 
     56        $dtExpected = new jDateTime(2006, 12, 14, 15, 28, 17); 
     57        $dt->sub($dur); 
     58        $this->assertEqual($dt, $dtExpected); 
     59    } 
     60 
     61    // Add one month to August, 31st, you would get something like "September,  
     62    // 31st", which gets "rounded" to October, 1st. For the moment, jDuration  
     63    // has no option to prevent from crossing the "month" barrier. 
     64    function testRelativeTricky(){ 
     65        $dur = new jDuration(array("month" => 1)); 
     66        $dt = new jDateTime(2007, 8, 31, 15, 28, 17); 
     67        $dtExpected = new jDateTime(2007, 10, 1, 15, 28, 17); 
     68        $dt->add($dur); 
     69        $this->assertEqual($dt, $dtExpected); 
     70    } 
     71 
     72    function testNegative(){ 
     73        $dur = new jDuration(-20); 
     74        $dt = new jDateTime(2007, 12, 25, 15, 28, 17); 
     75        $dtExpected = new jDateTime(2007, 12, 25, 15, 27, 57); 
     76        $dt->add($dur); 
     77        $this->assertEqual($dt, $dtExpected); 
     78    } 
     79 
     80    function testMultiplication(){ 
     81        $dur = new jDuration(array("year" => 1)); 
     82        $dur->mult(10); // Changed our mind, 10 years is better... 
     83        $dt = new jDateTime(2007, 1, 1, 23, 58, 3); 
     84        $dtExpected = new jDateTime(1997, 1, 1, 23, 58, 3); 
     85        $dt->sub($dur); 
     86        $this->assertEqual($dt, $dtExpected); 
     87    } 
     88 
     89    function testLeap1(){ 
     90        $dur = new jDuration(array("year" => 8)); 
     91        $dt = new jDateTime(2000, 2, 29, 12, 12, 12); 
     92        $dtExpected = new jDateTime(2008, 2, 29, 12, 12, 12); 
     93        $dt->add($dur); 
     94        $this->assertEqual($dt, $dtExpected); 
     95    } 
     96 
     97    function testLeap2(){ 
     98        $dur = new jDuration(array("year" => 7)); 
     99        $dt = new jDateTime(2000, 2, 29, 12, 12, 12); 
     100        $dtExpected = new jDateTime(1993, 3, 1, 12, 12, 12); 
     101        $dt->sub($dur); 
     102        $this->assertEqual($dt, $dtExpected); 
     103    } 
     104} 
     105?> 
  • lib/jelix/utils/jDuration.class.php

    old new  
     1<?php 
     2/** 
     3* @package     jelix 
     4* @subpackage  utils 
     5* @author      Florian Hatat 
     6* @copyright   2008 Florian Hatat 
     7* 
     8* @link        http://www.jelix.org 
     9* @licence     http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file 
     10*/ 
     11 
     12/** 
     13 * Utility to manipulate durations between two instants 
     14 * @package     jelix 
     15 * @subpackage  utils 
     16 */ 
     17class jDuration { 
     18    public $months; 
     19    public $days; 
     20    public $seconds; 
     21 
     22    /** 
     23     * Construct a new duration. 
     24     * You can specify the duration as a number of seconds, or as an associative  
     25     * array which may contain the keys "year", "month", "day", "hour", "minute"  
     26     * and "second". The former method defines an absolute duration (it will  
     27     * always add the same number of seconds to any given date/time), while the  
     28     * latter defines a relative duration (a duration of one month will for  
     29     * example represent different amounts of time depending on the start date). 
     30     * 
     31     * This class represents years as 12 months, minutes as 60 seconds and hours  
     32     * as 3600 seconds. There is no general conversion between months and days,  
     33     * nor between days and hours (because of DST). 
     34     * 
     35     * @param int/array representation of the duration as an absolute number of seconds, or an array. 
     36     */ 
     37    function __construct($init = 0){ 
     38        $this->days = $this->months = $this->seconds = 0; 
     39 
     40        if(is_array($init)){ 
     41            if(isset($init['year'])){ 
     42                $this->months += intval($init['year']) * 12; 
     43            } 
     44 
     45            if(isset($init['month'])){ 
     46                $this->months += intval($init['month']); 
     47            } 
     48 
     49            if(isset($init['day'])){ 
     50                $this->days += intval($init['days']); 
     51            } 
     52 
     53            if(isset($init['hour'])){ 
     54                $this->seconds += intval($init['hour']) * 3600; 
     55            } 
     56 
     57            if(isset($init['minute'])){ 
     58                $this->seconds += intval($init['minute']) * 60; 
     59            } 
     60 
     61            if(isset($init['second'])){ 
     62                $this->seconds += intval($init['second']); 
     63            } 
     64        } 
     65        elseif(is_int($init)){ 
     66            $this->seconds = $init; 
     67        } 
     68    } 
     69 
     70    /** 
     71     * Add a duration to the current duration 
     72     * @param jDuration the duration value 
     73     */ 
     74    function add($data){ 
     75        $this->days += $data->days; 
     76        $this->months += $data->months; 
     77        $this->seconds += $data->seconds; 
     78    } 
     79 
     80    /** 
     81     * Multiply the current duration by an integer 
     82     * @param int the scaling integer 
     83     */ 
     84    function mult($scale){ 
     85        if(is_int($scale)){ 
     86            $this->days *= $scale; 
     87            $this->months *= $scale; 
     88            $this->seconds *= $scale; 
     89        } 
     90    } 
     91} 
     92 
     93?> 
  • lib/jelix/utils/jDateTime.class.php

    old new  
    88* @contributor Florian Hatat 
    99* @copyright   2005-2006 Laurent Jouanneau 
    1010* @copyright   2007 Loic Mathaud 
    11 * @copyright   2007 Florian Hatat 
     11* @copyright   2007-2008 Florian Hatat 
    1212* @copyright   2001-2005 CopixTeam, GeraldCroes, Laurent Jouanneau 
    1313* 
    1414* This class was get originally from the Copix project (CopixDate.lib.php, Copix 2.3dev20050901, http://www.copix.org) 
     
    347347 
    348348    /** 
    349349     * Add a duration to the date. 
    350      * You can specify the duration in a jDateTime object (which then is not a date/time) 
    351      * or give each value of the duration 
    352      * @param jDateTime/int $year the duration value or a year with 4 digits 
     350     * You can specify the duration in a jDuration object or give each value of 
     351     * the duration. 
     352     * @param jDuration/int $year the duration value or a year with 4 digits 
    353353     * @param int $month month with 2 digits 
    354354     * @param int $day day with 2 digits 
    355355     * @param int $hour hour with 2 digits 
     
    357357     * @param int $second second with 2 digits 
    358358     */ 
    359359    public function add($year, $month=0, $day=0, $hour=0, $minute=0, $second=0) { 
    360         if ($year instanceof jDateTime) { 
     360        if ($year instanceof jDuration) { 
    361361            $dt = $year; 
    362362        } else { 
    363             $dt = new jDateTime($year, $month, $day, $hour, $minute, $second); 
     363            $dt = new jDuration(array("year" => $year, "month" => $month, 
     364                "day" => $day, "hour" => $hour, "minute" => $minute, 
     365                "second" => $second)); 
    364366        } 
    365         $t = mktime ( $this->hour +  $dt->hour, $this->minute + $dt->minute, $this->second + $dt->second
    366              $this->month + $dt->month, $this->day + $dt->day, $this->year + $dt->year); 
     367        $t = mktime($this->hour, $this->minute, $this->second + $dt->seconds
     368             $this->month + $dt->months, $this->day + $dt->days, $this->year); 
    367369 
    368370        $t = getdate ($t); 
    369371        $this->year = $t['year']; 
     
    376378 
    377379    /** 
    378380     * substract a <b>duration</b> to the date 
    379      * You can specify the duration in a jDateTime object (which then is not a date/time) 
    380      * or give each value of the duration 
    381      * @param jDateTime/int $year the duration value or a year with 4 digits 
     381     * You can specify the duration in a jDuration object or give each value of 
     382     * the duration. 
     383     * @param jDuration/int $year the duration value or a year with 4 digits 
    382384     * @param int $month month with 2 digits 
    383385     * @param int $day day with 2 digits 
    384386     * @param int $hour hour with 2 digits 
     
    386388     * @param int $second second with 2 digits 
    387389     */ 
    388390    public function sub($year, $month=0, $day=0, $hour=0, $minute=0, $second=0) { 
    389         if ($year instanceof jDateTime) { 
     391        if ($year instanceof jDuration) { 
    390392            $dt = $year; 
    391393        } else { 
    392394            $dt = new jDateTime($year, $month, $day, $hour, $minute, $second); 
    393395        } 
    394         $t = mktime ( $this->hour -  $dt->hour, $this->minute - $dt->minute, $this->second - $dt->second , 
    395              $this->month - $dt->month, $this->day - $dt->day, $this->year - $dt->year); 
    396  
    397         $t = getdate ($t); 
    398         $this->year = $t['year']; 
    399         $this->month = $t['mon']; 
    400         $this->day = $t['mday']; 
    401         $this->hour = $t['hours']; 
    402         $this->minute = $t['minutes']; 
    403         $this->second = $t['seconds']; 
     396        $dt->mult(-1); 
     397        $this->add($dt); 
    404398    } 
    405399 
    406400    /** 
    407401     * to know the duration between two dates. 
    408402     * @param jDateTime $dt  the date on which a sub will be made with the date on the current object 
    409      * @return jDateTime a jDateTime object which will contains <b>a duration</b> (not a date) 
     403     * @param bool $absolute  
     404     * @return jDuration a jDuration object 
    410405     */ 
    411     public function durationTo($dt){ 
    412         $t = mktime ( $dt->hour, $dt->minute,$dt->second , $dt->month, $dt->day, $dt->year ) 
    413             - mktime ( $this->hour, $this->minute,$this->second , $this->month, $this->day, $this->year ); 
    414         $t = getdate ($t); 
    415         return new jDateTime( $t['year']-1970,$t['mon']-1, $t['mday']-1, $t['hours']-1, $t['minutes'], $t['seconds']); 
     406    public function durationTo($dt, $absolute=true){ 
     407        if($absolute){ 
     408            $t = mktime($dt->hour, $dt->minute, $dt->second, 
     409                $dt->month, $dt->day, $dt->year) 
     410                - mktime($this->hour, $this->minute, $this->second, 
     411                    $this->month, $this->day, $this->year); 
     412            return new jDuration($t); 
     413        } 
     414        else{ 
     415            return new jDuration(array( 
     416                "year" => $dt->year - $this->year, 
     417                "month" => $dt->month - $this->month, 
     418                "day" => $dt->day - $this-> day, 
     419                "hour" => $dt->hour - $this->hour, 
     420                "minute" => $dt->minute - $this->minute, 
     421                "second" => $dt->second - $this->second 
     422            )); 
     423        } 
    416424    } 
    417425 
    418426    /** 
Download in other formats: Original Format