2013-03-06 11 views

Odpowiedz

8

Oto moja wersja @Yaslaw'scode.

Zostało poprawione zgodnie z aktualną społecznością PHP i wymaganiami PSR. Próbowałem też uczynić go bardziej czytelnym i prostym.

/** 
* @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; 
} 

A tu rozszerzenie do początkowego \DateInterval klasy:

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; 
    } 
} 

Może być stosowany tak:

$interval = new CustomDateInterval('P1Y2M3DT4H5M6S'); 

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

Mam nadzieję, że komuś pomóc , Twoje zdrowie!

2

Nie jestem guru C, ale w kodzie źródłowym funkcji konstruktora wartość nie wydają się być przechowywane w ogóle:

/* {{{ 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); 
} 
/* }}} */ 

Ani wydają się zrobić date_interval_initialize() funkcję:

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

Nie ma wbudowanej funkcji do tego celu, trzeba ją utworzyć samodzielnie. Jeśli nie chcesz, aby zastąpić DateInterval, spróbuj użyć metody statyczne:

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; 
     } 
    } 

Jeśli chcesz dodać funkcje (porównanie itd.) Można dodawać do niego.

+0

Nie podoba mi się ta implementacja. Jest to iteracja nad obiektem, który może mieć dowolną liczbę dodatkowych pól w przyszłości oprócz "dni" i już ma je w PHP 5.4. Klasy statyczne to także zły pomysł. I nie ma takiej funkcji jak "upper" w PHP. –

4

Można pracować z funkcji Format():

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

lub lepiej czytelny wersja (bez zerowej wartości w łańcuchach):

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;   
} 
Powiązane problemy