======[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}}