2010-04-05 92 views
82
$date1 = $date2 = new DateTime(); 
$date2->add(new DateInterval('P3Y')); 

現在$date1$date2包含同一日期 - 從現在起三年。我想創建兩個單獨的日期時間,一個是從一個字符串中解析出來的,另一個是添加了三年的日期時間。目前我已經破解它:如何深度複製DateTime對象?

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

但這似乎是一個可怕的黑客。是否有一種「正確」的方法來深入複製DateTime對象?

回答

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

更新:

如果要複製,而不是引用現有DT對象,使用clone,不=

+10

我用了一個新的DateTime中的例子來演示點,但現在假設DateTime是從一些不透明的API返回的,我不能再重新調用它。例如,我有一個處理訂單的函數,返回一個DateTime,客戶可以下一個訂單。調用函數來創建副本會產生我不想要的副作用。 – 2010-04-05 16:19:47

+0

我沒有真正測試過它,但是在php.net中提到它只適用於PHP 5.3及更高版本。 – 2013-02-01 01:02:02

+0

@hugo:是的,DateTime類需要PHP 5.3。 – 2013-03-28 17:19:38

74

克隆日期與clone操作:

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

克隆默認情況下淺,但對於一個日期時間足夠深。在你自己的對象中,你可以定義__clone()魔術方法來克隆當父對象改變時有意克隆的屬性(即子對象)。

(我不知道爲什麼文檔需要想克隆對象的一個​​很好的例子是GTK。誰在PHP使用GTK?)

+1

謝謝你的回答,但你怎麼知道它對於DateTime來說足夠深入?哪些屬性仍然是引用,哪些是通過值複製的?例如,我可以更改時間和時區,它不會影響克隆? – David 2013-09-27 12:08:16

+1

@David:我知道它對於DateTime來說足夠深,因爲我試過了,它對我很有用。我沒有嘗試改變時區或任何其他的東西,只是基本的時間和日期。 – rjmunro 2013-12-09 17:49:41

+3

使用Xdebug,var_dump($ date1)報告它包含'date'=> string,'timezone_type'=> int&'timezone'=> string。由於它看起來不包含任何數組或對象,只是基本的標量,淺層的克隆應該沒問題。 – 2017-01-25 02:14:11

30

PHP 5.5.0引進DateImmutableaddmodify這個類的方法返回新的對象。

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

請注意,不幸的是,您不能只用'DateTimeImmutable'交換'DateTime'。至少有'IntlDateFormatter :: formatObject'不喜歡不可變(返回false而不是格式化的字符串)。 – user276648 2016-09-14 03:43:32

+1

哦!儘管我早就夢想過,但我從來不知道這個存在。並一路回到5.5 ... – Ben 2017-02-13 14:32:33

+2

像一些noob我剛剛遇到了一個面向對象的陷阱,通過修改我在for循環中的DateTime對象:D這很好地解決了它... – Wilt 2017-03-21 17:37:58

0

你應該改變你的DateTimeDateTimeImmutable

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

,那麼你可以呼籲DateTime任何方法,而不必擔心它改變

+0

這實際上是一個不同問題的答案。 – 2017-09-20 19:01:39

+0

@BillyONeal我可能沒有完全解釋如何,但這是一個解決這個問題的方法,因爲這個問題的來源是如何調用'date2'上的add方法改變'date1'的值,並且沒有辦法複製'DateTime'變量的值,除非你有'DateTimeImmutable' – 2017-09-21 07:58:35