======[PHP] YDateTime & YDateInterval Classes====== DateTime und DateInterval sind zwar eine tolle Sache, jedoch fehlen mir gewisse Funktionalitäten. Dazu gehört das Runden in der DateTime genauso wie das bessere Arbeiten der Spezifikationsstrings im DateInterval ==YDateTime Erweiterungen zu DateTime== *round() Runden anhand eines DateInterval *round2() Runden anhand direkten Parametern *trunc() Abschneiden eines Datumteils *Ausgabe der Datumselemente ohne format. zB. echo $date->y; ==YDateInterval Erweiterungen zu DateInterval== *getSec() Berechnet die Intervalslänge in Sekunden *getSpecString() Gibt den Spezifikationsstring zurück (zB. P2DT5M) *getFullSpecString() Gibt den Spezifikationsstring inkl. 0-Werten zurück (zB. P0Y0M2DT0H5M0S) =====YDateTime===== /** * Erweiterungen zu DateTime: * - round() Runden anhand eines DateInterval * - round2() Runden anhand direkten Parametern * - trunc() Abschneiden eines Datumteils * - Ausgabe der Datumselemente ohne format */ class YDateTime extends DateTime{ const KEY_YEAR = 'y'; const KEY_MONTH = 'm'; const KEY_DAY = 'd'; const KEY_HOUR = 'h'; const KEY_MINUTE = 'i'; const KEY_SECOND = 's'; protected $dateParts = array(); protected $datePartsJson = <<format('Y-m-d H:i:s'); //Interne 'Variablen' definieren $this->dateParts = json_decode($this->datePartsJson, true); parent::__construct($time, $timezone); } /** * Akzeptiert nur Einträge aus $formatJson * @param $key: Alle KEY-Konstanten * @throws Exception */ public function __get($key){ if(array_key_exists($key, $this->dateParts)){ return (int)$this->format($this->dateParts[$key]['format']); }else{ throw new Exception("Property '{$key}' dosnt exists"); } } /** * Akzeptiert nur Einträge aus $formatJson * @param $key: Alle KEY-Konstanten * @param $value * @throws Exception */ public function __set($key, $value){ if(array_key_exists($key, $this->dateParts)){ if($this->dateParts[$key]['part'] ==='date'){ //Änderung im Datum parent::setDate( ($key == self::KEY_YEAR) ? $value : $this->y, ($key == self::KEY_MONTH) ? $value : $this->m, ($key == self::KEY_DAY) ? $value : $this->d); }elseif($this->dateParts[$key]['part'] ==='time'){ //Änderung in der Zeit parent::setTime( ($key == self::KEY_HOUR) ? $value : $this->h, ($key == self::KEY_MINUTE) ? $value : $this->i, ($key == self::KEY_SECOND) ? $value : $this->s); } }else{ throw new Exception("Property '{$key}' dosnt exists"); } } /** * @see DateTime::createFromFormat */ public static function createFromFormat($format, $time, $timezone=null ){ return new YDateTime(parent::createFromFormat($format, $time, $timezone)); } /** * rundet den Timestamp auf die Genauigkeit von DateInterval. * Es wird auf den ersten Eintrag im Interval gerundet. Alle * weiteren werden ignoriert: PT1H15M rundet also auf 1 Stunde genau * @todo Runden auf Datum ist nicht so ganz durchdacht * @param DateInterval $delta * @see round() */ public function round(DateInterval $delta, $mode = PHP_ROUND_HALF_UP){ if(!($delta instanceof YDateInterval)) $delta = new YDateInterval($delta); //Richtiger Part aussuchen und runden foreach($this->dateParts as $key => $format) { if($delta->$key != 0){ $this->$key = round( $this->$key / $delta->$key, 0, $mode) * $delta->$key; break; } } //Alles nachfolgende auf 0 setzen $this->trunc($key); } /** * Runden ohne die DateInterval Klasse * @param $key: Alle KEY-Konstanten * @see round() * @throws Exception */ public function round2($key, $precision, $mode = PHP_ROUND_HALF_UP){ if(array_key_exists($key, $this->dateParts)){ //Ein YDateInterval erstellen und $this->round() ausführen $delta = YDateInterval::createFromDateString("{$precision} {$this->dateParts[$key]['string']}"); $this->round($delta); }else{ throw new Exception("Property '{$key}' dosnt exists"); } } /** * Abschneiden der weiteren Informationen. * $date->trunc(YDateTime::KEY_DAY); schneidet alles nach dem Tag ab * @param $key: Alle KEY-Konstanten * @throws Exception */ public function trunc($key){ if(array_key_exists($key, $this->dateParts)){ $zeroFromNow = false; foreach($this->dateParts as $var => $format) { if(!$zeroFromNow && $key == $var){ $zeroFromNow = true; }elseif($zeroFromNow){ $this->$var = $format['zero']; } } }else{ throw new Exception("Property '{$key}' dosnt exists"); } } } ====Beispiel zu YDateTime==== define('C_TIME_FORMAT', 'd.m.Y H:i:s'); require_once 'YDateTime.php'; //Jetzt $now = new YDateTime(); var_dump($now->format(C_TIME_FORMAT)); //round() auf 15 Minuten $o = $now; $o->round(New YDateInterval('PT15M')); var_dump($o->format(C_TIME_FORMAT)); //round2() auf 20 Minuten $o = $now; $o->round2(YDateTime::KEY_MINUTE, 20); var_dump($o->format(C_TIME_FORMAT)); //trunc() auf Tage $o = $now; $o->trunc(YDateTime::KEY_DAY); var_dump($o->format(C_TIME_FORMAT)); Ausgabe string(19) "01.10.2013 13:11:14" string(19) "01.10.2013 13:15:00" string(19) "01.10.2013 13:20:00" string(19) "01.10.2013 00:00:00" =====YDateInterval===== /** * Erweiterungen zu DateInterval: * - getSec() Berechnet die Intervalslänge in Sekunden * - getSpecString() Gibt den Spezifikationsstring zurück (zB. P2DT5M) * - getFullSpecString() Gibt den Spezifikationsstring inkl. 0-Werten zurück (zB. P0Y0M2DT0H5M0S) */ class YDateInterval extends DateInterval{ /** * Konstrukteur * $interval_spec kann entweder ein Spezifikationsstring sein oder ein * DateInterval-Objekt. * @param Variant */ public function __construct($interval_spec){ //Falls es ein DateInterval ist, den $interval_spec auslesen if($interval_spec instanceof DateInterval) { $interval_spec = self::getStaticFullSpecString($interval_spec); } parent::__construct($interval_spec); } /** * Erstellt ein YDateInterval aus einem normalen DateInterval * @param DateInterval $delta * @return YDateInterval */ static function createFromDateInterval(DateInterval $delta){ return new YDateInterval(self::getStaticSpecString($delta)); } /** * Berechnet die Intervalslänge in Sekunden * @return number */ function getSec(){ return ($this->s) + ($this->i * 60) + ($this->h * 60 * 60) + ($this->d * 60 * 60 * 24) + ($this->m * 60 * 60 * 24 * 30) + ($this->y * 60 * 60 * 24 * 365); } /** * Gibt den lesbaren Spezifikationsstring zurück * @exampe: 'P2DT5M' * @return String */ public function getSpecString(){ return self::getSpecString($this); } /** * Gibt einen Spezifikationsstring zurück. Im gegensatz zu getSpecString() * werden auch die Parameter mit angegeben die 0 sind. Um mit PHP zu arbeiten * reicht dieser aus. * @exampe: 'P0Y0M2DT0H5M0S' * @return String */ public function getFullSpecString(){ return self::getStaticFullSpecString($this); } /** * statische Version von getSpecString um den String von einem DateInterval * zu ermitteln * @exampe: 'P0Y0M2DT0H5M0S' * @param DateInterval * @return String */ public static function getStaticFullSpecString(DateInterval $delta){ return $delta->format('P%yY%mM%dDT%hH%iM%sS'); } /** * statische Version von getFullSpecString um den String von einem DateInterval * zu ermitteln * @exampe: 'P2DT5M' * @param DateInterval * @return String */ public static function getStaticSpecString(DateInterval $delta){ //Read all date-parts there are not 0 $date = array_filter(array('Y' => $delta->y, 'M' => $delta->m, 'D' => $delta->d)); //Read all time-parts there are not 0 $time = array_filter(array('H' => $delta->h, 'M' => $delta->i, 'S' => $delta->s)); //Convert each part to spec-Strings foreach($date as $key => &$value) $value = $value.$key; foreach($time as $key => &$value) $value = $value.$key; //Create date spec-string $spec = 'P' . implode('', $date); //add time spec-string if(count($time)>0) $spec .= 'T' . implode('', $time); return $spec; } } {{tag>PHP Library}}