Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
43 / 43
YearMonth
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
5 / 5
30
100.00% covered (success)
100.00%
43 / 43
 yearMonthDeduce
100.00% covered (success)
100.00%
1 / 1
10
100.00% covered (success)
100.00%
10 / 10
 yearMonthGenerator
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
13 / 13
 addYears
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 addMonths
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 valid
100.00% covered (success)
100.00%
1 / 1
13
100.00% covered (success)
100.00%
18 / 18
<?php
namespace ia\Date;
use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
class YearMonth {
    /* ///// create a yearMonth ///// */
    public static function yearMonthDeduce($anyDate = 'now') {
        if(empty($anyDate) ||
            (is_string($anyDate) &&
                (strcasecmp($anyDate, 'NOW()') === 0 || strcasecmp($anyDate,'NOW()') === 0 || strcasecmp($anyDate,'today()') === 0)
            )
        ){
            // @codeCoverageIgnoreStart
            return Date('Y-m');
            // @codeCoverageIgnoreEnd
        }
        if($anyDate instanceof DateTimeInterface) {
            return $anyDate->format('Y-m');
        }
        if(is_numeric($anyDate)) {
            return Date('Y-m', $anyDate);
        }
        if(is_string($anyDate) && self::valid($anyDate)) {
            return $anyDate;
        }
        return  Date('Y-m', strtotime($anyDate));
    }
    /* ///// generator ///// */
    // @usage foreach(yearMonthGenerator('2018-11','2019-04') as $tomes)
    //  remember $array = iterator_to_array(yearMonthGenerator($from, $to));
    public static function yearMonthGenerator(string $from, string $to) {
        $oneMonth = new DateInterval('P1M');
        $current = new DateTime($from.'-01');
        if($from <= $to) {
            while($from <= $to) {
                yield $from;
                $current->add($oneMonth);
                $from = $current->format('Y-m');
            }
            return;
        }
        while($from >= $to) {
            yield $from;
            $current->sub($oneMonth);
            $from = $current->format('Y-m');
        }
    }
/* ///// operations, add & substract ///// */
    public static function addYears(string $yearMonth, int $numberOfYears = 1) {
        return  ((int)substr($yearMonth, 0, 4) + $numberOfYears) . substr($yearMonth, 4);
    }
    public static function addMonths(string $yearMonth, int $numberOfMonths = 1) {
        return Date('Y-m',  strtotime( ($numberOfMonths < 0 ? '' : '+') . "$numberOfMonths Month", strtotime("$yearMonth-01")) );
    }
/* ///// validate ///// */
    public static function valid(string $yearMonth, $min = null, $max = null) {
        if(strlen($yearMonth) !== 7) {
            return false;
        }
        $parts = explode('-', $yearMonth);
        if(count($parts) !== 2) {
            return false;
        }
        if(strlen($parts[0]) !== 4 || !is_numeric($parts[0])) {
            return false;
        }
        if(strlen($parts[1]) !== 2 || !is_numeric($parts[1])) {
            return false;
        }
        if($parts[1] < '01' || $parts[1] > '12') {
            return false;
        };
        if(!empty($min)) {
            // todo string, actual, anterior, siguiente, ?
                if($yearMonth < self::yearMonthDeduce($min)) {
                    return false;
                }
        }
        if(!empty($max)) {
                if($yearMonth > self::yearMonthDeduce($max)) {
                    return false;
                }
        }
        return true;
    }
}