2013-03-06 5 views

Antwort

8

Hier ist meine Version von @Yaslaw'scode.

Es wird gemäß einer aktuellen PHP-Community und PSR-Anforderungen verbessert. Ich habe auch versucht, es lesbarer und direkter zu machen.

/** 
* @param \DateInterval $interval 
* 
* @return string 
*/ 
function dateIntervalToString(\DateInterval $interval) { 

    // Reading all non-zero date parts. 
    $date = array_filter(array(
     'Y' => $interval->y, 
     'M' => $interval->m, 
     'D' => $interval->d 
    )); 

    // Reading all non-zero time parts. 
    $time = array_filter(array(
     'H' => $interval->h, 
     'M' => $interval->i, 
     'S' => $interval->s 
    )); 

    $specString = 'P'; 

    // Adding each part to the spec-string. 
    foreach ($date as $key => $value) { 
     $specString .= $value . $key; 
    } 
    if (count($time) > 0) { 
     $specString .= 'T'; 
     foreach ($time as $key => $value) { 
      $specString .= $value . $key; 
     } 
    } 

    return $specString; 
} 

Und hier ist die Erweiterung der ursprünglichen \DateInterval Klasse:

class CustomDateInterval extends \DateInterval 
{ 
    public function __toString() 
    { 
     // Reading all non-zero date parts. 
     $date = array_filter(array(
      'Y' => $this->y, 
      'M' => $this->m, 
      'D' => $this->d 
     )); 

     // Reading all non-zero time parts. 
     $time = array_filter(array(
      'H' => $this->h, 
      'M' => $this->i, 
      'S' => $this->s 
     )); 

     $specString = 'P'; 

     // Adding each part to the spec-string. 
     foreach ($date as $key => $value) { 
      $specString .= $value . $key; 
     } 
     if (count($time) > 0) { 
      $specString .= 'T'; 
      foreach ($time as $key => $value) { 
       $specString .= $value . $key; 
      } 
     } 

     return $specString; 
    } 
} 

Es kann wie folgt verwendet werden:

$interval = new CustomDateInterval('P1Y2M3DT4H5M6S'); 

// Prints "P1Y2M3DT4H5M6S". 
print $interval . PHP_EOL; 

ich es hoffe, dass jemand helfen , Prost!

2

Ich bin kein C-Guru aber in dem Quellcode der Konstruktorfunktion der Wert scheint nicht überhaupt gespeichert werden:

/* {{{ proto DateInterval::__construct([string interval_spec]) 
    Creates new DateInterval object. 
*/ 
PHP_METHOD(DateInterval, __construct) 
{ 
    char *interval_string = NULL; 
    int interval_string_length; 
    php_interval_obj *diobj; 
    timelib_rel_time *reltime; 
    zend_error_handling error_handling; 

    zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &interval_string, &interval_string_length) == SUCCESS) { 
     if (date_interval_initialize(&reltime, interval_string, interval_string_length TSRMLS_CC) == SUCCESS) { 
      diobj = zend_object_store_get_object(getThis() TSRMLS_CC); 
      diobj->diff = reltime; 
      diobj->initialized = 1; 
     } else { 
      ZVAL_NULL(getThis()); 
     } 
    } 
    zend_restore_error_handling(&error_handling TSRMLS_CC); 
} 
/* }}} */ 

Weder scheint die date_interval_initialize() Funktion zu tun:

static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *format, int format_length TSRMLS_DC) 
{ 
    timelib_time  *b = NULL, *e = NULL; 
    timelib_rel_time *p = NULL; 
    int    r = 0; 
    int    retval = 0; 
    struct timelib_error_container *errors; 

    timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); 

    if (errors->error_count > 0) { 
     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); 
     retval = FAILURE; 
    } else { 
     if(p) { 
      *rt = p; 
      retval = SUCCESS; 
     } else { 
      if(b && e) { 
       timelib_update_ts(b, NULL); 
       timelib_update_ts(e, NULL); 
       *rt = timelib_diff(b, e); 
       retval = SUCCESS; 
      } else { 
       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse interval (%s)", format); 
       retval = FAILURE; 
      } 
     } 
    } 
    timelib_error_container_dtor(errors); 
    return retval; 
} 
0

Dafür gibt es keine eingebaute Funktion, Sie müssen eine selbst erstellen. Wenn Sie DateInterval nicht außer Kraft setzen wollen, versuchen Sie statische Methoden zu verwenden:

class DateIntervalUtils{ 
    public static function getSpecString(DateInterval $i){ 
     $stat ="P"; 
     foreach($i as $key=>$value){ 
      if($key !=="days"){ 
       if($key=="h"){ 
        $stat.="T"; 
       } 
       $stat.=$value.upper($key); 
      } 
      } 
      return $stat; 
     } 
    } 

Wenn Sie Funktionen hinzufügen möchten (Vergleich usw.), die Sie hinzufügen können.

+0

Ich mag diese Implementierung nicht. Es wird über ein Objekt iteriert, das neben "Tagen" beliebig viele zusätzliche Felder enthalten kann und in PHP 5.4 bereits vorhanden ist. Statische Klassen sind ebenfalls eine schlechte Idee. Und in PHP gibt es keine solche Funktion wie "Upper". –

4

Sie können mit dem Format() Funktion arbeiten:

echo $obj->format('P%yY%mM%dDT%hH%iM%sS'); 

Oder besser lesbare Version (ohne Null-Werte im String):

function getSpecString(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;   
}