DateTime 객체를 어떻게 깊게 복사합니까?


118
$date1 = $date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));

이제 $date1$date2현재로부터 3 년 - 같은 날짜가 포함되어 있습니다. 두 개의 개별 날짜 시간을 만들고 싶습니다. 하나는 문자열에서 구문 분석되고 다른 하나는 3 년이 추가되었습니다. 현재 나는 다음과 같이 해킹했습니다.

$date2 =  new DateTime($date1->format(DateTime::ISO8601));

그러나 그것은 끔찍한 해킹처럼 보입니다. DateTime 개체를 자세히 복사하는 "올바른"방법이 있습니까?

답변:


171
$date1 = new DateTime();
$date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));

최신 정보:

기존 DT 객체를 참조하는 대신 복사하려면 clone, 아니라를 사용하십시오 =.

$a = clone $b;


12
요점을 설명하기 위해 예제에서 새 DateTime을 사용했지만 지금은 다시 호출 할 수없는 일부 불투명 한 API에서 DateTime이 반환된다고 가정합니다. 예를 들어, 고객이 다음에 주문할 수있는 날짜 / 시간을 반환하는 주문을 처리하는 함수가 있습니다. 복사본을 만드는 함수를 호출하면 원하지 않는 부작용이 발생합니다.
Billy ONeal 2010

실제로 테스트하지는 않았지만 php.net에서 PHP 5.3 이상에서만 사용할 수 있다고 언급되어 있습니다.
hugo der hungrige 2013

@hugo : 예, DateTime 클래스에는 PHP 5.3이 필요합니다.
Billy ONeal 2013 년

11
PHP에 대해 이해하고 있다고 생각했을 때 새로운 연산자에 대해 배웠습니다.
kr094

기존 Carbon 객체를 다른 변수에 복사하려면 이렇게해야했습니다. 이것은 효과가 있었다.
racl101

111

복제 연산자로 날짜를 복제하십시오 .

$date1 = new DateTime();
$date2 = clone $date1;
$date2->add(new DateInterval('P3Y'));

클론은 기본적으로 얕지만 DateTime에 충분히 깊습니다. 자신의 개체 __clone()에서 부모 개체가 변경 될 때 복제 할 수있는 속성 (즉, 자식 개체)을 복제 하는 마법 방법을 정의 할 수 있습니다 .

(문서에서 객체를 복제해야하는 좋은 예가 GTK라고 생각하는 이유를 모르겠습니다. 누가 PHP에서 GTK를 사용합니까?)


1
답변 해 주셔서 감사합니다.하지만 DateTime에 대해 충분히 깊다는 것을 어떻게 알 수 있습니까? 어떤 속성이 참조로 남아 있고 어떤 속성이 값으로 복사됩니까? 예를 들어 시간과 시간대를 변경할 수 있는데 복제에 영향을주지 않습니까?
David

1
@David : 나는 그것을 시도했기 때문에 DateTime에 대해 충분히 깊다는 것을 알고 있으며 그것은 나를 위해 일했습니다. 시간대 나 다른 것을 변경하지 않고 기본 시간과 날짜 만 변경했습니다.
rjmunro

3
Xdebug를 사용하여 var_dump ($ date1)는 'date'=> string, 'timezone_type'=> int & 'timezone'=> string이 포함되어 있다고보고합니다. 배열이나 객체를 포함하지 않는 것처럼 보이므로 기본 스칼라 만 있으면 얕은 복제가 좋습니다.
CJ Dennis

46

PHP 5.5.0은 DateTimeImmutable을 도입했습니다 . 이 클래스의 추가수정 메서드는 새 개체를 반환합니다.

$date1 = new DateTimeImmutable();
$date2 = $date1->add(new DateInterval('P3Y'));

4
안타깝게도 DateTimea를 DateTimeImmutable. 적어도 IntlDateFormatter::formatObject불변을 좋아하지 않는 것이 있습니다 ( false형식이 지정된 문자열 대신 반환 ).
user276648

1
오! 나는 오랫동안 꿈꿔 왔지만 이것이 존재한다는 것을 결코 알지 못했습니다. 그리고 다시 5.5에서 ...
Ben

2
어떤 멍청이처럼 나는 DateTimefor 루프에서 내 객체를 수정함으로써 객체 지향적 함정을 만났다 . : D 이것은 멋지게 해결했다 ...
Wilt

3
@ user276648이 버그는 이제 php 7.1.5에서 수정되었습니다. php.net/ChangeLog-7.php#7.1.5
jontro

11

TLDR :

$date1 = new DateTime();
$date2 = (clone $date1)->modify('+3 years');

(Shallow copy is enaugh- Deep copy-ing DateTime is (current ) no sense )

그렇게 간단합니다 :)

설명 "php create datetime object from another datetime":

  1. clone키워드는 정기적으로 만드는 얕은의 사본을 - enaugh을이 경우에 (=> 아래 참조 이유)
  2. 래핑 ()하면 새로 생성 된 객체를 반환하는 표현식이 다음과 같이 평가됩니다.clone
  3. ->modify() 따라서 호출되고 새 개체를 수정합니다.
  4. DateTime::modify(...) 문서 :

    메서드 체인에 대한 DateTime 개체를 반환하고 실패하면 FALSE를 반환합니다.

  5. $date2이제 새로 생성 및 수정 된 클론 / 복사본이 포함되지만 $date1변경되지 않습니다.

여기 에 카피 가 필요하지 않은 이유 :

참조 인 속성의 대상을 복사해야하는 경우에만 전체 복사 / 복제가 필요 하지만 다음과 같습니다.

class TestDateTime extends DateTime{
  public function test(){
   //*this* way also outputs private variables if any...
   var_dump( get_object_vars($this) );    
  }
}
$test = (new TestDateTime())->test();

출력 :

array(3) {
  ["date"]=>
  string(26) "2019-08-21 11:38:48.760390"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}

따라서 참조가 없으며 단순한 유형 만 => 복사 할 필요가 없습니다 .


1

당신은 당신을 변경해야 DateTime합니다DateTimeImmutable

// from date time
$date = \DateTimeImmutable::createFromMutable($mutableDate)

그런 다음 DateTime변경에 대해 걱정하지 않고 모든 메서드를 호출 할 수 있습니다.


이것은 정말로 다른 질문에 대한 답입니다.
Billy ONeal 2017 년

난 안가 완전히 어떻게 설명해야 할 수도 있습니다, 그러나 이것은이 문제의 원인으로이 문제에 대한 솔루션입니다 @BillyONeal 메소드 호출하는 방법입니다 adddate2값을 변경 date1하고 값 복사 할 수있는 방법이 없습니다 DateTime당신이이 없으면 변수DateTimeImmutable
호세인 Shahdoost
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.