Is it possible to clone a DateTime Obj and call a method all in the same statement? I know it can be done on object instantiation. I tried a test script on cloning but it didn't work.
<?php
// instead of
$nextDay = clone $startDate;
$nextDay->add(new DateInterval('P1D'));
// something like this instead
$test = ['test' => (clone $nextDay)->add(new DateInterval('P1D'))];
?>
It is in PHP7, but not in PHP5
$startDate = new DateTime();
$endDate = (clone $startDate)->add(new DateInterval('P7D'));
echo $endDate->format('Y-m-d');
will work in PHP7
EDIT
However, you can get start and end date simply in PHP5 by taking advantage of DateTimeImmutable, where the add() method leaves the original value unchanged, but return a new object:
$startDate = new DateTimeImmutable();
$endDate = $startDate->add(new DateInterval('P7D'));
echo $startDate->format('Y-m-d'), PHP_EOL;
echo $endDate->format('Y-m-d'), PHP_EOL;
Related
this is what I have got:
$_SESSION["chosen_exam_start_time"] = new DateTime();
$schedule_date = $_SESSION["chosen_exam_start_time"];
$schedule_date->setTimeZone(new DateTimeZone('Europe/London'));
$triggerOn = $schedule_date->format('Y-m-d H:i:s');
so I have a date passed within the session called "chosen_exam_start_time".
Now what I am struggling to do is add on $triggerOn.
So currently if I do
die(var_dump($triggerOn));
I get :
string(19) "2016-03-28 17:17:57"
What I want to do is if I have another variable which tells me a value like 10, how would I be able to add that value on to the $triggerOn. So that it will be:
string(19) "2016-03-28 17:27:57"
What I have done up to now is :
$_SESSION["chosen_exam_start_time"] = new DateTime();
$schedule_date = $_SESSION["chosen_exam_start_time"];
$schedule_date->setTimeZone(new DateTimeZone('Europe/London'));
$triggerOn = $schedule_date->format('Y-m-d H:i:s');
$value = 10;
$triggerOn->modify((int) $value.' minute');
die(var_dump($triggerOn));
However this die is not printing anything out now
I doesn't make sense to make any sort of calculation using strings. Just imagine you had this:
$price = 'Thirty five point nine';
$discount = 'Twenty percent';
... and you wanted to apply the discount ;-)
If your current architecture makes it impossible to keep the original DateTime object (I don't know, I don't have enough information for that) you'd better create a new one:
<?php
$triggerOn = '2016-03-28 17:17:57';
$minutes_to_add = 10;
$triggerOnDateTime = new DateTime($triggerOn, new DateTimeZone('Europe/London'));
$triggerOnDateTime->modify( sprintf('%d minutes', $minutes_to_add) );
$triggerOn = $triggerOnDateTime->format('Y-m-d H:i:s');
You are looking for the modify function on a datetime object.
$trigger->modify((int) $value.' minute');
Note I just pulled this from the Carbon Library, which is a very useful wrapper for DateTime giving you a good bit of syntactic sugar such as:
$trigger->addMinutes(10);
I have a date:
$launched=new DateTime();
I would like to create a new DateTime using $launched but adding days. Something like:
$expired=new DateTime($launched->modify("+$expiry days"));
How can I do this?
Assuming you are using PHP 5.5 or newer DateTimeImmutable makes this easy:
$launched = new DateTimeImmutable();
$expired = $launched->modify("+$expiry days");
DateTimeImmutable does not modify the original object which is what DateTime does. So you can just assign the resulting object return by modify() to a variable and have a new object with a date in the future.
If you are using an older, and obsolete, version of PHP you can clone the original object to achieve the same result:
$launched = new DateTimeImmutable();
$expired = clone $launched;
$expired->modify("+$expiry days");
I have created different vars using date_format from one datetime object $date_obj.
$date_obj = date_create($date);
$year = date_format($date_obj, 'Y');
$month = date_format($date_obj, 'm');
$day = date_format($date_obj, 'd');
However I have read (lost source) that this is bad practice? Instead I should create a new datetime object each time because the original object isn't referenced, but directly manipulated.
$date_obj_1 = date_create($date);
$year = date_format($date_obj_1, 'Y');
$date_obj_2 = date_create($date);
$month = date_format($date_obj_2, 'm');
$date_obj_3 = date_create($date);
$day = date_format($date_obj_3, 'd');
Is this true?
The DateTime object is an object, and therefore is passed by reference.
In your example above this won't matter, because you only format a date, you do not manipulate it. However, if you use a DateTime object as an argument in a function and inside this function you manipulate the object, your changes will be visible outside of that function:
function addDays($date,$days){
$date->add(new DateInterval($days.' days'));
}
$date_obj_1 = date_create($date);
$formatedDate1 = date_format($date_obj_1, 'Y-m-d');
addDays($date_obj_1,10);
$formatedDate2 = date_format($date_obj_1, 'Y-m-d');
In the above example $formatedDate1 is different from $formatedDate1 because $date_obj_1 was passed by reference
EDIT: for a detailed explanation on my above snipped look at the comments section. #Xatoo explained it pretty good.
date_format isn't manipulating the DateTime object. What you do is the equivalent of:
$dateObject = new DateTime($date);
$year = $dateObject->format('Y');
$month = $dateObject->format('m');
$day = $dateObject->format('d');
This is absolutely fine, dateObject is not changed by calling the format method on it.
I want to get the date of yesterday of the current date in a specifc time zone.
I tried like this, but it is not working:
$date = new DateTime(NULL, new DateTimeZone('Pacific/Wake'));
$yesterday = $date->modify( '-1 day' );
$yesterday = $yesterday->format('Y-m-d');
I am still getting today's date.
This problem, according to the documentation for the modify() method, seems to entirely depend on which version of php you're using. In this case, method chaining(which is what you're attempting to do is called), is only available on php version 5.3.0 and up, according to the changelog on the previously linked docs.
That in mind, it explains why your code didn't work, and #Deryck's did. If you ever do upgrade your php version, or get your host to upgrade it, you could likely reduce those three lines to two:
$date = new DateTime(NULL, new DateTimeZone('Pacific/Wake'));
$date = $date->modify( '-1 day' )->format('Y-m-d');
Not much of an improvement, I realize, but there's your reason for why it failed to work.
Below are two of the methods I see of getting around this; one is creation of a class.. which seems like overkill to me unless this is apart of something grander... the other is a creation of a function. Both shove the extra lines into something that takes up less space, in a sense.
class DT {
private $now; //can be null
private $timezone; //DateTimeZone object
public function __construct($tz_str, $now = NULL) {
$this->now = $now;
$this->timezone = new DateTimeZone($tz_str);;
}
public function mod($mod,$format) {
$dt = new DateTime($this->now, $this->timezone);
$dt->modify($mod);
return $dt->format($format);
}
}
function mod_formatted_zone($tz_str, $mod, $format, $now = NULL) {
$timezone = new DateTimeZone($tz_str);
$dt = new DateTime($now,$timezone);
$dt->modify($mod);
return $dt->format($format);
}
The use of either is simple; in the case of the class, it'd be something like..
$dt = new DT('Pacific/Wake');
echo $dt->mod('-1 day', 'Y-m-d');
While in the case of the function, it'd simply be..
echo mod_formatted_zone('Pacific/Wake', '-1 day', 'Y-m-d');
Seems to work once you don't re-assign the $date variable unnecessarily. See below:
<?php
$date = new DateTime(NULL, new DateTimeZone('Pacific/Wake'));
$date->modify("-1 day");
$date = $date->format("Y-m-d");
// echo $date; // just in case you wanna echo - ya dig
?>
View demo
FYI:
Wake Island Time Zone (UTC+12:00)
Which means 1 day before is actually today (for me at least, on the western hemisphere).
I want to get the date of yesterday of the current date in a specifc time zone.
You can specify relative dates in the DateTime constructor. This will work for you:-
$yesterday = new DateTime('- 1 day', new DateTimeZone('Pacific/Wake'));
var_dump($yesterday);
Proof!.
Here is an example of the code I used:
<?php
date_default_timezone_set("Europe/London");
$date1 = date_create("2014-04-05");
$date2 = $date1;
date_add($date2, new DateInterval("P1M"));
echo "Date 1: ".date_format($date1, "Y-m-d")."<br/>";
echo "Date 2: ".date_format($date2, "Y-m-d")."<br/>";
?>
The result for this would be:
Date 1: 2014-05-05
Date 2: 2014-05-05
I was expecting the result of:
Date 1: 2014-04-05
Date 2: 2014-05-05
How can I get the expected result and fix this?
I can only use PHP, HTML and CSS so no jQuery or Javascript please.
The clone keyword is what you need.
$date2 = clone $date1;
When an object is cloned, a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references.
If your object $date2 holds a reference to another object $date1 which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.
Source
This is due to how objects are assigned by reference since PHP 5; after assignment, changes made to one object are reflected in the other as well.
The generic solution is to clone the object:
$date2 = clone $date1;
In this case you could also use the DateTimeImmutable interface (introduced in 5.5) which creates new instances whenever you attempt to modify it, e.g. using ->add().
$date1 = new DateTimeImmutable('2014-04-05');
$date2 = $date1;
$date2 = $date2->add(new DateInterval('P1M'));
echo "Date 1: ".date_format($date1, "Y-m-d")."<br/>";
echo "Date 2: ".date_format($date2, "Y-m-d")."<br/>";
This code can be made easier by doing this:
$date1 = new DateTimeImmutable('2014-04-05');
$date2 = $date1->add(new DateInterval('P1M'));