Is it possible in PHP to change the DateTime() to a custom time difference. Like adding it 20 min and everytime I call new DateTime() I would get those extra 20 min to the current date.
I thought about __construct() but didn't see how to fix it.
I can use a function of course, but just curious to know if its possible to change the prototype new DateTime()
Yes, it's possible:
$date = new DateTime();
$date->modify("+20 minutes"); //or whatever value you want
Example online
Ilia Rostovtsev's answer is a good one for achieving your goal. Alternatively you can also use the DateInterval class with DateTime::add(). Personally, I prefer that one because you don't need to know how strings need to look like while DateInterval uses a standard like P1d for a day.
I wouldn't use inheritance to get a DateTime class including your wished behaviour. Instead you can create some kind of factory which contains Ilia's code (and every other code that is part for the object creation). The interval can be added as parameter. Your added interval, your 20 minutes should be stored in a constant in case you need to change that interval in the future while technically being able to use other intervals than 20 minutes.
You can do this all in one line:-
$date = (new \DateTime())->add(new \DateInterval('PT20M'));
That would be my preferred way of doing it.
See it working in PHP >= 5.3
Related
I need to check which financial markets are open but i didn't found api for it.
I want to make it with php, and i need to give for example 2 periods of time:
$open = 09:00:00;
$close = 16:00:00;
and add a if statement as a checker if time is between those, and i will run a cron job for it.
All i want is to get the correct condition to check if time is on this period/frame.
Tried this but i dont know how to implement further:
$datetime1 = new DateTime('03:55:06');//start time
$datetime2 = new DateTime('11:55:06');//end time
$interval = $datetime1->diff($datetime2);
echo $interval->format('%H hours %i minutes %s seconds');//
First of all, you should consider using the same zoned datetime for the financial market you are targeting.
For Paris as an example, you will use "Europe/Paris" to get the local datetime inside that timezone.
After that point, you can go further with your between condition. And the best way to get that is to use the DateInterval class, with its own DateInterval::diff method.
You can check out the official PHP documentation here : https://www.php.net/manual/fr/class.dateinterval.php
And the diff method : https://www.php.net/manual/fr/datetime.diff.php
And I would compare the current zoned datetime to the start of the working interval : it must be equal or later.
I would compare it to the end of the working hours interval : it must be before or equal.
So you have everything you need to write it correctly now.
So it seems like the PHP DateTime class allows you to use simple relative language strings such a next Monday 12:00 to create objects associated with relative dates.
The Problem
The use case I'd like to achieve is to omit the day ("Monday") from the above string, and create a DateTime object for the next instance of 06:00.
This presents a challenge because the code may be running at 07:00, in which case the string 06:00 will return a date which is in the past, whereas if we run the code at 05:00 (or anytime before 06:00), we will get the correct result.
Note: As an addendum, I don't want to have to do a bunch of complicated arithmetic and want to leverage the DateTime class to its fullest to keep myself from any sneaky little TimeZone or leap year issues.
My Question
How can I use the PHP DateTime class to obtain a DateTime object for the next instance of a certain time (without supplying the day as well)?
I created a PHP extension for the DateTime API called dt. You can find it here. Using it for this task is very simple. Some Examples:
$dt = dt::create("today 06:00");
if($dt->isPast()) {
$dt->modify("+ 1Day");
}
echo $dt;
Optionally, you can always set a time zone as the second parameter.
$time = "06:00";
$dt = dt::create("today $time","Africa/Johannesburg");
//:
The class works with special chains which can contain conditions. This allows you to create an expression that does the job with the create method alone.
$dt = dt::create("today 6:00|{{?YmdHis<NOW}}+1 Day");
The class also works with cron expressions.
$cron = "0 6 * * 1-5";//every Mo-Fr at 6:00
$dt = dt::create('now')->nextCron($cron);
Always delivers the next time 6:00 for Monday to Friday. At the weekend, the next time is Monday 6:00.
The Solution
Here's how I ended up solving this...
/*
* Simple function that returns a DateTime object representing the next instance of the time
* supplied by the $timeString parameter.
*
* $timeString: A string representing the time you wish to process, in 24h notation (i.e.
* '06:00' for 6:00am).
*/
function getNextTimeInstance($timeString){
// First, grab an instance of the current moment as a DateTime object ('now' is optional).
$rightNow = new DateTime('now');
// Basic initializations for the object we want to use.
$processedTime = new DateTime();
// Change the Timezone if you need to do so.
$processedTime->setTimezone(new DateTimeZone('Africa/Johannesburg'));
// Set the time for our working DateTime to the time we want (i.e. '06:00').
$processedTime->modify($timeString);
// If the next instance of this time we're trying to process is in the past
// (meaning it is "less than" the current moment).
if($rightNow > $processedTime){
// Simply add one day to our working DateTime object.
$processedTime->modify('+1 day');
}
// Return the DateTime objects that represents the next instance of that time.
return $processedTime;
}
I relied heavily on the following documentation to reach this result:
The PHP DateTime class.
The list of date formats that the PHP DateTime class will accept as inputs.
The list of supported TimeZone strings that PHP will accept.
I hope this helps anyone else stuck in the same situation as myself, and if anyone else has a more elegant solution, please feel free to contribute.
So,
I know a lot of requests and question has been askeb about this subject but none really worked for my case... I'm working on a liscensing api with php (supposed to be easy) and I get a string date (2000-01-01) from my db and the length of the subscription. So I'm creating a DateTime Object with it using this :
$created_at = date_create($result["created_at"]);
date_add($created_at, date_interval_create_from_date_string($result["length"]." days"));
But for some unknowed reason, It seems I can't get the current date in a DateTime object so I can just compare them with <>=. Even if I use date_sub() or date_diff() It still require two DateTime object. I'm really deseperate at this point so I figured I could ask for some help.
Hope I didn't miss anything obvious
You can use the 'now' attribute,
$today = new DateTime('now'); to get the current time.
Don't forget to set your timeregion in your php.ini to be able to get the right time.
And if you want to compare them, you can use date_diff and then
$var->format('%r') to get the value.
%r is going to be empty if the result is positive.
Good luck!
The DateTimeZone constructor only accepts a region name:
new DateTimeZone('Europe/London');
And not an offset from UTC:
new DateTimeZone('+01:00'); // Unknown or bad timezone (+01:00)
However, it is possible to obtain such a DateTimeZone from a DateTime:
(new DateTime('2012-12-28T00:00:00+01:00'))->getTimezone()->getName(); // +01:00
So this is a bit weird. Is there a way to directly obtain a DateTimeZone from an offset?
In addition to RafaĆ's answer, the simplest way I've found so far is:
DateTime::createFromFormat('O', '+01:00')->getTimezone();
Edit
This was a bug that has been fixed in PHP 5.5.10. It now works!
Modern answer:
new DateTimeZone('+0100');
Documentation:
http://php.net/manual/en/datetimezone.construct.php
Check out this function.
http://pl1.php.net/manual/en/function.timezone-name-from-abbr.php
You'll need to convert hours to seconds and pass them as second parameter.
Sth. like new DateTimeZone(timezone_name_from_abbr('', 3600, 0)) should work.
I dont think that there is any predefined way you wanna go. But if you declare any global function that will return you date and time with the offset added, it might help you.
Example :
function getDateTime($format="dd-mm-YY"){
$currDate= date($format);
$currDate=date($format,strtotime("+1 day",$currDate); // or whatever needed instead of +1 day
}
PHP's DateTime class has the two methods add() and sub() to add or subtract a time span from a DateTime object. This looks very familiar to me, in .NET I can do the same thing. But once I tried it, it did very strange things. I found out that in PHP, those methods will modify the object itself. This is not documented and the return value type indicates otherwise. Okay, so in some scenarios I need three lines of code instead of one, plus an additional local variable. But then PHP5's copy by reference model comes into play, too. Just copying the object isn't enough, you need to explicitly clone it to not accidently modify the original instance still. So here's the C# code:
DateTime today = DateTime.Today;
...
if (date < today.Add(TimeSpan.FromDays(7)) ...
Here's the PHP equivalent:
$today = new DateTime('today');
...
$then = clone $today;
$then->add(new DateInterval('P7D'));
if ($date < $then) ...
(I keep a copy of today to have the same time for all calculations during the method runtime. I've seen it often enough that seconds or larger time units change in that time...)
Is this it in PHP? I need to write a wrapper class for that if there's no better solution! Or I'll just stay with the good ol' time() function and just use DateTime for easier parsing of the ISO date I get from the database.
$today = time() % 86400;
...
if ($date < $today + 7 * 86400) ...
Time zones not regarded in these examples.
Update: I just found out that I can use the strtotime() function as well for parsing such dates. So what's the use for a DateTime class in PHP after all if it's so complicated to use?
Update^2: I noticed that my $today = ... thing above is garbage. Well, please just imagine some correct way of getting 'today' there instead...
It looks like you will definitely have to make a clone of the object. There does not seem to be a way to create a copy of the DateTime object any other way.
As far as I can see, you could save one line:
$today = new DateTime('today');
...
$then = clone $today;
if ($then->add(new DateInterval('P7D')) < $then) ...
I agree this isn't perfect. But do stick with DateTime nevertheless - write a helper class if need be. It is way superior to the old date functions: It doesn't have the year 2038 bug, and it makes dealing with time zones much, much easiert.