dateFormat, $date)->getTimestamp(); }, explode($this->dateSeparator, $range))); if ($_range['to'] && $_range['to'] < $_range['from']) throw new Exception("Date 'to' before date 'from'"); return $_range; }, explode($this->rangeSeparator, $str)); } private function arrToStr($arr) { return implode($this->rangeSeparator, array_map(function ($range) { return implode($this->dateSeparator, array_map(function ($date) { if (!$date) return ''; return date($this->dateFormat, $date); }, $range)); }, $arr)); } private static function sort(&$ranges) { uasort($ranges, function($a, $b) { if ($a['from'] == $b['from']) { if ($a['to'] == $b['to']) return 0; if (!$a['to']) return 1; if (!$b['to']) return -1; return ($a['to'] < $b['to']) ? -1 : 1; } return ($a['from'] < $b['from']) ? -1 : 1; }); } private function implodeRanges($ranges) { if (is_array($ranges)) { $ranges = implode($this->rangeSeparator, array_filter($ranges, function($range) { if ($range) return true; return false; })); } return $ranges; } private function _merge($ranges) { $ranges = $this->implodeRanges($ranges); if (!$ranges) throw new Exception("DataRanges::_merges - bad ranges"); $ranges = $this->strToArr($ranges); self::sort($ranges); $result = []; foreach ($ranges as $range) { if (!$result) $result[] = $range; else { if (!end($result)['to']) break; $k = key($result); if ($range['from'] == $result[$k]['from']) $result[$k]['to'] = $range['to']; elseif ((!$range['to']) || ($range['to'] > $result[$k]['to'])) { if ($range['from'] > $result[$k]['to']) $result[] = $range; else $result[$k]['to'] = $range['to']; } } } return $this->arrToStr($result); } private static function lt($date1, $date2) { if (!$date1) return false; if (!$date2) return true; return ($date1 < $date2); } private static function gt($date1, $date2) { if (!$date2) return false; if (!$date1) return true; return ($date1 > $date2); } private static function le($date1, $date2) { return (!self::gt($date1, $date2)); } private static function ge($date1, $date2) { return (!self::lt($date1, $date2)); } private static function min($dates) { if ((!is_array($dates)) || (!$dates)) throw new Exception("DateRanges::min - bad arguments"); $min = null; foreach ($dates as $date) { if ($min === null) { $min = $date; continue; } if (self::lt($date, $min)) $min = $date; } return $min; } private static function max($dates) { if ((!is_array($dates)) || (!$dates)) throw new Exception("DateRanges::max - bad arguments"); $max = null; foreach ($dates as $date) { if ($max === null) { $max = $date; continue; } if (self::gt($date, $max)) $max = $date; } return $max; } private function _common($rangesA, $rangesB) { $rangesA = $this->implodeRanges($rangesA); $rangesB = $this->implodeRanges($rangesB); if (!($rangesA && $rangesB)) throw new Exception("DataRanges::_common - bad ranges"); $rangesA = $this->strToArr($rangesA); $rangesB = $this->strToArr($rangesB); self::sort($rangesA); self::sort($rangesB); $ranges = []; foreach ($rangesA as $rangeA) { foreach ($rangesB as $rangeB) { // if ($rangeA['from'] == $rangeB['from'] && $rangeA['to'] == $rangeB['to']) { // $ranges[] = $rangeA; // continue; // } $range = [ 'from' => self::max([$rangeA['from'], $rangeB['from']]), 'to' => self::min([$rangeA['to'], $rangeB['to']]), ]; //print_r($range); if (self::le($range['from'], $range['to'])) { // || ($range['from'] == $range['to'] && ($rangeA['from'] == $rangeB['from'] || $rangeA['to'] == $rangeB['to']))) { $ranges[] = $range; } } } if (!$ranges) return null; return $this->_merge($this->arrToStr($ranges)); } private function _days($ranges) { $ranges = $this->implodeRanges($ranges); if (!$ranges) throw new Exception("DataRanges::_days - bad ranges ({$ranges})"); $ranges = $this->strToArr($ranges); $result = (int) 0; foreach ($ranges as $range) { if (!$range['from']) throw new Exception("DataRanges::_days - bad date from"); if (!$range['to']) return -1; if ($range['to'] < $range['from']) throw new Exception("DataRanges::_days - date to before date from"); $result += round(($range['to'] - $range['from']) / 86400); } return round($result); } public function __construct($dateFormat = null, $rangeSeparator = null, $dateSeparator = null) { if ($dateFormat !== null) $this->dateFormat = $dateFormat; if ($rangeSeparator !== null) $this->rangeSeparator = $rangeSeparator; if ($dateSeparator !== null) $this->dateSeparator = $dateSeparator; } public static function merge($ranges, $dateFormat = null, $rangeSeparator = null, $dateSeparator = null) { $obj = new DateRanges($dateFormat, $rangeSeparator, $dateSeparator); return $obj->_merge($ranges); } public static function common($rangesA, $rangesB, $dateFormat = null, $rangeSeparator = null, $dateSeparator = null) { $obj = new DateRanges($dateFormat, $rangeSeparator, $dateSeparator); return $obj->_common($rangesA, $rangesB); } public static function days($ranges, $dateFormat = null, $rangeSeparator = null, $dateSeparator = null) { $obj = new DateRanges($dateFormat, $rangeSeparator, $dateSeparator); return $obj->_days($ranges); } } class DateRanges_debug extends DateRanges { }