Php. Работа с временными отрезками через DateInterval.
Главная >> Backend >> Php. Работа с временными отрезками через DateInterval.
Php. Работа с временными отрезками через DateInterval.
Работа с датой и временем нереально частая задача на php, особенно в разрезе работы в временными отрезками и/или периодами. Наиболее оптимальный вариант — работать с помощью объекта DateInterval.
Класс DateInterval используется для указания временного периода. При создании объекта следует указать период в специальном формате, например:
Если присмотреться — стает понятно, что означает «шифр» в конструкторе:
P: период
Y: года
M: месяца
D: дни
T: время
H: часы
M: минуты
S: секунды
Приведу пару примеров, чтобы не писать 10 абзацов теории:
P2Y 2 года
P3M 3 месяца
P12D 12 дней
P3H 3 часа
P1М 1 минута
P11S 11 секунд
P2Y7M11DT1H14M10S 2 года, 7 месяцев, 11 дней, 1 час, 14 минуты и 10 секунды
ОЧЕНЬ ВАЖНО. В случае создания объекта DateInterval со значением 13 месяцев — т.е. «P13M», данные будут преобразованы в валидные значения «1 год и 1 месяц», а не 13 месяцев!
О том, как проводить манипуляции с датами — добавлять, вычитать их Вы можете почитать в этой статье.
Похожие записи
В статье несколько ошибок.
Это неверно. Если в интервале нужно указать время, то перед блоком времени нужно добавить букву T.
Должно получиться так
So here is the situation. In my db table i have a column called expire_date, where i put a certain date for each row. So for example the expire date is 28-04-2012
11 Answers 11
First get the date in one month with php:
Then you can do a select:
And there you have an array with all the items who expire in less than one month. If you want exactly the ones that expire in 1 month:
I’m surprised this answer is missing here:
Maybe you should do that in SQL rather than PHP no?
If you want to do in in PHP, here is a cleaner way than @Expert want to be
Notice that I use = and not less than, because if you just compare that it’s less than one month, then you will be emailing the users every day during the last month.
You can make use of the ADDDATE() function in your MySQL Query.
If you have an index on your expire_date column, this can be done quite fast if you query for entries with a WHERE statement like:
(More about CURDATE() right here)
If you do that every day exactly once it will only select all people at max once and not send them the email twice since it only selects those that are exactly 1 month away from their expire date.
Of course this works without any additional care about the specific representation of dates if you use a DATE fieldtype in your MySQL table.
increment date by one month
Let’s say I have a date in the following format: 2010-12-11 (year-mon-day)
With PHP, I want to increment the date by one month, and I want the year to be automatically incremented, if necessary (i.e. incrementing from December 2012 to January 2013).
18 Answers 18
I needed similar functionality, except for a monthly cycle (plus months, minus 1 day). After searching S.O. for a while, I was able to craft this plug-n-play solution:
I used clone because add modifies the original object, which might not be desired.
this returns a timestamp that can be used with the date function
You can use DateTime::modify like this :
UPDATE january 2021 : correct mistakes raised by comments
This solution has some problems for months with 31 days like May etc.
Exemple : this jumps from 31st May to 1st July which is incorrect.
To correct that, you can create this custom function
Then you can use it like that :
This will compensate for February and the other 31 day months. You could of course do a lot more checking to to get more exact for ‘this day next month’ relative date formats (which does not work sadly, see below), and you could just as well use DateTime.
Both DateInterval(‘P1M’) and strtotime(«+1 month») are essentially blindly adding 31 days regardless of the number of days in the following month.
Please first you set your date format as like 12-12-2012
After use this function it’s work properly;
Here 12-12-2012 is your date and +2 Months is increment of the month;
DateInterval::__construct — Создает новый объект DateInterval
Описание
Создает новый объект DateInterval.
Список параметров
Формат начинается с буквы P, за » период «. Длина каждого периода описывается целым значением и следующим за ним указателем периода. Если длина периода содержит время, то его описанию должна предшествовать буква T.
| Указатель периода | Описание |
|---|---|
| Y | года |
| M | месяцы |
| D | дни |
| W | недели. Преобразуется в дни, поэтому не может быть использован совместно с D. |
| H | часы |
| M | минуты |
| S | секунды |
Указатели должны записываться от большей величины (слева) к меньшей величине (направо). То есть года должны быть до месяцев, месяцы до дней, дни до минут и так далее. Таким образом, один год и четыре дня должны быть представлены как P1Y4D, но не P4D1Y.
Задать период также можно в виде даты и времени. Пример одного года и четырех дней может описываться как P0001-00-04T00:00:00. Но значения в этом формате не должны выходить за рамки допустимых значений даты и времени (т.е., 25 часов недопустимо)
Ошибки
Бросает Exception, если interval_spec не может быть распознан в качестве интервала.
Примеры
Пример #1 Пример использования DateInterval
Результат выполнения данного примера:
Смотрите также
DateTime::add
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Description
Adds the specified DateInterval object to the specified DateTime object.
Parameters
Return Values
Returns the DateTime object for method chaining or false on failure.
Examples
Example #1 DateTime::add() example
The above examples will output:
Example #2 Further DateTime::add() examples
The above example will output:
Example #3 Beware when adding months
= new DateTime ( ‘2000-12-31’ );
$interval = new DateInterval ( ‘P1M’ );
The above example will output:
See Also
User Contributed Notes 12 notes
Another simple solution to adding a month but not autocorrecting days to the next month is this.
(Also works for substracting months)
$dt = new DateTime(«2016-01-31»);
Hope this helps someone.
Here is a solution to adding months when you want 2014-10-31 to become 2014-11-30 instead of 2014-12-01.
/**
* Class MyDateTime
*
* Extends DateTime to include a sensible addMonth method.
*
* This class provides a method that will increment the month, and
* if the day is greater than the last day in the new month, it
* changes the day to the last day of that month. For example,
* If you add one month to 2014-10-31 using DateTime::add, the
* result is 2014-12-01. Using MyDateTime::addMonth the result is
* 2014-11-30.
*/
class MyDateTime extends DateTime
<
If you need add() and sub() that don’t modify object values, you can create new methods like this:
class DateTimeEnhanced extends DateTime <
$interval = DateInterval :: createfromdatestring ( ‘+1 day’ );
If you use fraction of seconds, you may have surprises. It only occurs when the sum of the floating point parts results in exactly 1 second (0.5 + 0.5 ou 0.3 + 0.7, for example). See these cases at intervals slightly bigger than 1 second:
To resolve, add 1 second to the interval and f property must be negative (-1.0 plus original value):
What you can do with this function/method is a great example of the philosophy: «just because you can do it doesn’t mean you should». I’m talking about two issues: (1) the number of days in the month which varies from months 1-12 as well as for month 2 which could be leap year (or not); and then issue (2): what if there is the need to specify a large quantity of an interval such that it needs to be re-characterized into broader-scoped intervals (i.e. 184 seconds ==> 3 minutes-4 seconds). Examples in notes elsewhere in the docs for this function illustrate both issues and their undesired effects so I won’t focus on them further. But how did I decide to handle? I’ve gone with four «public» functions and a single «private» function, and without giving you a bunch of code to study, here are their summaries.
**Results/goals.
—any number of days/hours/minutes/seconds can be passed in to add/subtractTime and all of «Y/M/D/H/M/S» values get adjusted as you would expect.
—using adjustYear/Month lets you pass +/- values and only «Y/M» values get modified without having undesirable effects on day values.
—a call to the «recharacterize» function helps ensure proper and desired values are in the intervals prior to calling date_add to let it do its work.
/* results:
1383458399 1383458399 2013-11-03 01:59:59 EDT
1383458400 1383462000 2013-11-03 02:00:00 EST
noticed how the second column went from 1383458399 to 1383462000 even though only 1 second was added?
*/
$TodaySQL = substr(date(DATE_ISO8601 ),0,10)
$LastYearSQL = date(‘Y.m.d’,strtotime(«-1 years»))
$NextMonthEndSQL = date(‘Y.m.d’,strtotime(«+1 months»))
// handy little SQL date formats
//Today
2021-03-24
//Last year
2020.03.24
//Next month
2021.04.24
Remark, that calculations on date are not defined as bijective operations. The Summertime is integrated by mixing two concepts. You should test it beforehead.
Datetime will correct a date after each summation, if a date (29.2.2021 => 1.3.2021) or a datetime (29.3.2020 2:30 am (Europe/Berlin) => 29.3.2020 3:30 or 29.3.2020 1:30)
Be careful when using this function, I may have happened upon a bug in PHP7.
My code is as follows
//get date from post or else fill with today’s date
if (isset($_POST[«from»]))
<
$from = date_create($_POST[«from»]);
>else<
$from = date_create(date(«Y-m-d»));
>
The resultant output is
$from = 2015-12-11
$to = 2015-12-11
In actuality the result should be
$from = 2015-12-10
$to = 2015-12-11
to fix this i needed to change the code to
//get date from post or else fill with today’s date
if (isset($_POST[«from»]))
<
$from = date_create($_POST[«from»]);
>else<
$from = date_create(date(«Y-m-d»));
>
This isn’t strictly the code I wanted. Possible bug?



