2013-03-06 30 views
5

Ben DateInterval bu nesne örneğini olduğunu varsayalım:DateInterval nesnesinden "interval_spec" dizesini almak mümkün mü?

$obj=new DateInterval("P1Y12D"); 

Şimdi bunun $obj örneği ile birkaç güzel şeyler yapabilirsiniz ama nesneden "P1Y12D" dize o çıkmak istiyorum demek, olmadan düz mümkündür Sınıfı geçersiz kılmak mı gerekiyor?

Bunun için bir yöntem bulamadım, belki de öyle.

cevap

8

İşte @Yaslaw'scode benim versiyonu.

Güncel bir PHP topluluğuna ve PSR gereksinimlerine göre geliştirilmiştir. Ayrıca daha okunaklı ve anlaşılır bir hale getirmeye çalıştım. Ben Birine yardımcı olacağını umuyoruz

$interval = new CustomDateInterval('P1Y2M3DT4H5M6S'); 

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

:

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

Böyle kullanılabilir:

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

Ve burada ilk \DateInterval sınıfa uzantısı Şerefe!

2

Bir C gurusu değilim ama yapıcı işlevinin kaynak kodunda değeri hiç saklanabilir görünmüyor:

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

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

Ne date_interval_initialize() fonksiyonunu yapmak gibi görünüyor

0

Bunu yapmak için yerleşik bir işlev yoktur, kendiniz bir tane oluşturmanız gerekir. Eğer DateInterval geçersiz istemiyorsanız Eğer statik yöntemleri kullanmayı deneyin:

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

sen (vb karşılaştırma) işlevlerini eklemek isterseniz buna ekleyebilirsiniz.

+0

Bu uygulamayı sevmiyorum. Gelecekte "günler" dışında herhangi bir ek alana sahip olabilecek bir nesne üzerinde yinelemekte ve zaten bunları PHP 5.4'te barındırmaktadır. Statik sınıflar da kötü bir fikirdir. Ve PHP'de 'upper' gibi bir işlev yoktur. –

4

Sen biçimi() fonksiyonu ile çalışabilirsiniz:

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

Ya (String Sıfır Değerler olmadan) daha iyi bir okunabilir Versiyon:

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;   
} 
İlgili konular