PHP DateTime modify gives wrong date on leap year - php

I'm using PHP's DateTime object to manipulate dates. I found a strange case where the result date seems wrong:
$dt = new DateTime('2020-02-29 23:59:59');
$dt->modify('-1 year');
echo $dt->format('Y-m-d H:i:s');
This code gives 2019-03-01 23:59:59 instead of 2019-02-28 23:59:59. I believe it is due to 2020 having a Feb. 29th yet I have no clue how to fix this issue.
Note that the modifier can be anything, not just -1 year. A solution that would isolate the year number minus one wouldn't fit my needs.

I figured out myself a work around that seems to work.
I noted that things work well with first day of the month:
$dt = new DateTime('2020-02-01 00:00:01');
$dt->modify('-1 year');
echo $dt->format('Y-m-d H:i:s'); // 2019-02-01 00:00:01
From this statement, I just added a few steps when I need to manipulate "end of the month" dates:
$dt = new DateTime('2020-02-29 23:59:59');
$dt->modify('first day of this month');
$dt->modify('-1 year');
$dt->modify('last day of this month');
echo $dt->format('Y-m-d H:i:s'); // 2020-02-28 23:59:59

Related

PHP dateTime previous month of 31 Dec is wrong

I have this:
$previousMonth = new DateTime('2019-12-31');
$previousMonth->modify('-1 month');
My understanding is '-1 month' should modify the object regardless of number of days in that month, or?
Naturally what should I get or expect to get is end of Nov(2019-11-30) but what I get is first of December(the same month).
BTW if I change the date to '2019-12-30'(one day prior) then it will be end of Nov.
If my initial assumption is not correct, then what is the best alternative to reliably calculate the previous month?
Any thoughts?
The simplest and easiest way to get the last month in php is
$previousMonth = date("Y-n-j", strtotime("last day of previous month"));
Same as been suggested on other thread Getting last month's date in php
$date = "2019-12-31 00:00:00";
echo date('Y-m-d', strtotime($date . '-1month'));
This prints out 2019-12-01 as the 31/11 does not exist.
The following doesn't answer your question but may help in the future. I like to use Carbon when working with dates. Your issue could be resolved quite simply with this.
https://carbon.nesbot.com/
It has many functions and is extremely simple to use, and it can be installed with Composer.
To get the last day of the previous month, you can get the first day of the current month and substract 1 second or 1 day :
$previousMonth = new DateTime('2019-12-31');
$previousMonth->modify($previousMonth->format('Y-m-01')); // date is 2019-12-01 00:00:00
$previousMonth->modify('-1 sec');
echo $previousMonth->format('Y-m-d H:i:s') . PHP_EOL; // Outputs 2019-11-30 23:59:59
$previousMonth->modify('+1 sec'); // set back the original date 2019-12-01 00:00:00
$previousMonth->modify('-1 day');
echo $previousMonth->format('Y-m-d H:i:s'); // Outputs 2019-11-30 00:00:00

how to set 00:00:00 for DateTime

What I want to get are
today's 00:00:00
week start day's 00:00:00
month start day's 00:00:00
year start day's 00:00:00
So I write the code,
$today = new \DateTime();
$weekStart = new \DateTime();
$monthStart = new \DateTime();
$yearStart = new \DateTime();
$weekStart->modify('last sunday');
$monthStart->modify('first day of this months');
$yearStart->modify('first day of this year');
print $today->format('Y-m-d h:i:s')."\n";
print $weekStart->format('Y-m-d h:i:s')."\n";
print $monthStart->format('Y-m-d h:i:s')."\n";
print $yearStart->format('Y-m-d h:i:s')."\n";
It gave me the result:
2018-11-13 09:34:02
2018-11-11 12:00:00
2018-11-01 09:34:02
2018-11-01 09:34:02
I have two questions.
How can I make each DateTime 00:00:00??
How can I get the first day of year???
PHP's date parsing is somewhat tricky. Here's the code snippet which does what you want:
$today = new \DateTime('midnight');
$weekStart = new \DateTime('midnight last sunday');
$monthStart = new \DateTime('midnight first day of this month');
$yearStart = new \DateTime('midnight first day of january this year');
echo $today->format('Y-m-d H:i:s')."\n";
echo $weekStart->format('Y-m-d H:i:s')."\n";
echo $monthStart->format('Y-m-d H:i:s')."\n";
echo $yearStart->format('Y-m-d H:i:s')."\n";
DateTime value can be set upon construction; there's no need to call DateTime::modify().
Add midnight to get the time set to 00:00:00.
first day this year doesn't work in PHP, you need to use first day of january this year instead.
Reference: PHP Documentation of relative date formats.
you can try:
$date->setTime(0, 0, 0);
$date = new DateTime('2012-07-22');
echo $date->format('Y-m-d 00:00:00');
NO need to create a object of datetime(), use above code to get current date with time 00:00:00

Using just strtotime, 0 am first day of this month in PHP?

echo mydate(strtotime('1 am first day of this month'));
Above works with result 2017-10-01 01:00:00, but I have difficulty to do it for 0 am. Neither 24am, 24pm, 0pm, first second works.
Use midnight:
echo mydate(strtotime('midnight first day of this month'));
Demo
Better to use DateTime for date and time manipulations,
$date = new DateTime('midnight first day of this month');
echo $date->format('Y-m-d H:i:s');
or if there is need to UnixTimestamp : $date->format('U');
or echo $date->getTimestamp();

Using Date time diff with timezones

I found a link earlier regarding using time diffs and getting the difference in minutes, hours and days:
How to get time difference in minutes in PHP
I was trying this:
$date1 = new DateTime('first day of this month', new DateTimeZone('Europe/Amsterdam'));
$date2 = new DateTime('first day of this month', new DateTimeZone('Europe/London'));
print_r($date1->format('Y-m-d H:i:s'));
print_r($date2->format('Y-m-d H:i:s'));
The output was like:
2013-12-01 13:00:36
2013-12-01 12:00:36
Then used this:
$diff = $date2->diff($date1);
print_r($diff);
But then i get 0 in all the differences. I want to get the difference between the two without using strtotime.. I is it outputing 0?
Your expectation doesn't make sense, since there is no difference. 2013-12-01 13:00:36 Amsterdam and 2013-12-01 12:00:36 London are the exact same point in time in human history. What you appear to expect is the offset difference between the London and Amsterdam timezones (i.e. GMT and GMT+1 differ by 1), but that has nothing to do with concrete timestamps.
You want to calculate the offset.Use DateTimeZone::getOffset()
$dateTimeZoneAmsterdam = new DateTimeZone("Europe/Amsterdam");
$dateTimeZoneLondon = new DateTimeZone("Europe/London");
$dateTimeAmsterdam = new DateTime('first day of this month', $dateTimeZoneAmsterdam);
$dateTimeLondon = new DateTime('first day of this month', $dateTimeZoneLondon);
$timeOffset = $dateTimeZoneAmsterdam->getOffset($dateTimeLondon);
print_r($timeOffset); // 3600
You are close. Try DateTime::diff

DateTime modify string for first day of current year

im looking for the DateTime modify String for the first day of the year (now 1. January 2011). I tried the following:
<?php
$time = new DateTime();
// works as expected, the first day of the current month
$time->modify('first day of this month');
echo $time->format('c')."\n";
// this doesn't work. I also tried several other ways
$time->modify('first day of january');
echo $time->format('c')."\n";
>
I know there are other ways to retrieve the date, but I search an string for DateTime->modify() no other solution.
You should specify the year too, as you can see in this example:
"first day of January 2008"
from the official doc.
Update: It works on php version >= 5.3.6
On v5.5.6
echo date('Y-m-d', strtotime('first day of January this year'));
Result: 2013-01-01
To get the day of the week for the first of the year
or the first day of the month
<?php
//This is for a given month
$m="May";
// this id for this month
//$m=date('F');
//if you want the day of Sunday instead D use lower case l
echo date('D', strtotime('first day of January this year'));
echo "<br>". date("D", strtotime('first day of'. $m ));
?>
Result Wed For May with D
Result Wednesday with l
This work for me (PHP 5.6 - not tested on older version)... as we talk for DateTime object
//Get current datetime
$now = new DateTime();
$now->modify('first day of January this year');
echo $now->format('Y-m-d');
// Print (current year)-01-01
echo (new DateTime())->modify('first day of January this year')->format('Y-m-d');

Categories