2013-03-06 36 views
5

Nói rằng tôi có trường hợp đối tượng này DateInterval:Có thể lấy chuỗi "interval_spec" từ đối tượng DateInterval không?

$obj=new DateInterval("P1Y12D"); 

Bây giờ tôi có thể làm vài điều khá với điều đó $obj dụ, nhưng nói rằng tôi muốn nhận ra rằng "P1Y12D" chuỗi từ đối tượng, là nó thẳng nếu không có sự cần phải ghi đè lên lớp học?

Tôi không tìm thấy phương pháp cho việc này, có thể bạn đã làm.

Trả lời

8

Dưới đây là phiên bản của tôi về @Yaslaw'scode.

Nó được cải thiện theo yêu cầu của cộng đồng PHP hiện tại và PSR. Tôi cũng đã cố gắng làm cho nó dễ đọc hơn và dễ hiểu hơn.

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

Và đây là phần mở rộng của lớp ban đầu \DateInterval:

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

Nó có thể được sử dụng như thế này:

$interval = new CustomDateInterval('P1Y2M3DT4H5M6S'); 

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

Tôi hy vọng nó sẽ giúp một ai đó , chúc mừng!

2

Tôi không phải là một guru C nhưng trong mã nguồn của hàm constructor giá trị dường như không được bảo quản ở tất cả:

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

Cả dường như làm date_interval_initialize() chức năng:

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

Không có chức năng tích hợp để thực hiện điều đó, bạn phải tự mình tạo. Nếu bạn không muốn ghi đè DateInterval, cố gắng sử dụng phương pháp tĩnh:

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

Nếu bạn muốn thêm chức năng (so sánh vv), bạn có thể thêm vào nó.

+0

Tôi không thích triển khai này. Nó đang lặp qua một đối tượng có thể có bất kỳ số lượng trường bổ sung nào trong tương lai ngoài "ngày" và nó đã có chúng trong PHP 5.4. Các lớp tĩnh cũng là một ý tưởng tồi. Và không có hàm như 'upper' trong PHP. –

4

Bạn có thể làm việc với các định dạng() chức năng:

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

Hoặc ở phiên bản có thể đọc được tốt hơn (không có Zero-Giá trị trong 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;   
} 
Các vấn đề liên quan