Many ways to generate dates, lots of them getting you in trouble...
$testDate = date('Y-m-d');
echo $testDate;
// 2017-05-26
$testDate = date('Y-m-d H:i:s');
echo $testDate;
// 2017-05-26 16:25:08
date() accepts a timestamp as parameter:
string date ( string $format [, int $timestamp = time() ] )
A timestamp is the number of seconds since the 1st January 1970
No Time Zone are taken with timestamp
// the mktime function take 6 parameters
// BE CAREFUL WITH THE PARAMETERS ORDER
$hour = 0 ;
$minute = 0 ;
$second = 0 ;
$month = 10 ;
$day = 24 ;
$year = 2016 ;
$timestampToApply = mktime($hour, $minute, $second, $month, $day, $year);
$testDate = date('Y-m-d', $timestampToApply);
echo $testDate; // 2016-10-24
// get the last day of last month, today is 2017-05-26
$month = date('m')-1 ;
$year = date('Y') ;
// create the timestamp of last month
$timestampFirstDayOfLastMonth = mktime(0, 0, 0, $month, 1, $year) ;
// the timestamp is on last month, I will get the last day, so number 30
$lastDayOfTheMonth = date('t', $timestampFirstDayOfLastMonth);
$timestampLastDayOfLastMonth = mktime(0, 0, 0, $month, $lastDayOfTheMonth, $year);
// I have the correct timestamp, I can call the function date
$lastDayOfLastMonth = date('Y-m-d', $timestampLastDayOfLastMonth);
echo $lastDayOfLastMonth; // 2017-04-30
// get the last day of last month, today is 2017-05-26
// made in one line
$lastDayOfLastMonth = date(
'Y-m-d',
mktime(
0,
0,
0,
date('m')-1,
date('t', mktime(0, 0, 0, date('m')-1, 1, date('Y'))),
date('Y')
)
);
echo $lastDayOfLastMonth; // 2017-04-30
echo date('Y-m-d', mktime(0, 0, 0, 1, 33, 2017));
// 2017-02-02
I will try to put the date 33 January 2017
It will set to the date according to 31 January + 2 days
// Today is Tuesday 2017-05-26
$firstDayOfLastMonth = date('Y-m-d', strtotime("first day of last month"));
// => 2017-04-01
$lastDayOfLastMonth = date('Y-m-d', strtotime("last Day of Last Month"));
// => 2017-04-30
$lastSunday = date('Y-m-d', strtotime("last Sunday"));
// => 2017-05-21
$mondayOfLastWeek = date('Y-m-d', strtotime("last Monday of Last Week"));
// => 2017-05-15
// WARNING !! first Specific day of last week will not give you what you want
echo date('Y-m-d'); // "2017-05-26"
$date = date('Y-m-d', strtotime("First Monday of Last Week"));
// => 2017-04-24
// WARNING !! if you are the 31th, Last month will give you the day one of this month
$timeThirtyOneOctober = mktime(0,0,0,10,31,2017);
$wrongDate = date('Y-m-d', strtotime("Last Month", $timeThirtyOneOctober));
// => 2017-10-01
// Only way to get it right is by using this
$goodDate = date('Y-m-d', strtotime("Last Day of Last Month", $timeThirtyOneOctober));
// => 2017-09-30
// WARNING, some phrases seems Ok but does not work at all
$wrongDate = date('Y-m-d', strtotime("Monday of Last Week"));
// => 1970-01-01
// How do you construct the 15th of last month ?? you cannot with strtotime
$dayFifteenOfThisMonth = date('Y-m-d', mktime(0, 0, 0, date('m'), 15, date('Y')));
// => 2017-05-15
$firstDayOfThisMonth = new \DateTime('first day of this month');
$firstDayOfThisMonth->format('Y-m-d');
// => 2017-05-01
$dayFifteenOfThisMonth = new \DateTime();
$dayFifteenOfThisMonth->setTime(0, 0, 0);
$dayFifteenOfThisMonth->setDate(
(int) $dayFifteenOfThisMonth->format('Y'),
(int) $dayFifteenOfThisMonth->format('m'),
15
);
$dayFifteenOfThisMonth->format('Y-m-d');
// => 2017-05-15
// trap on the First Specific day of last Week
// Today is 2017-05-26
$date = new DateTime("First Monday of Last Week");
$date->format('Y-m-d') ;
// => 2017-04-24
// Trap on phrases that seems normal but does not work at all
$wrongDate = new DateTime("Monday of Last Week");
$wrongDate->format('Y-m-d');
// Fatal error: Uncaught Exception: DateTime::__construct():
// Failed to parse time string (Monday of Last Week)
The only difference is the DateTimeImmutable cannot be altered once created.
If you do, it will create a new DateTime Object
createFromMutable
// create date at day 15th of this month
$date = new \DateTime();
$date->setTime(0, 0, 0);
$date->setDate((int) $date->format('Y'), (int) $date->format('m'), 15);
$dayFifteenOfThisMonth = \DateTimeImmutable::createFromMutable($date);
echo $dayFifteenOfThisMonth->format('Y-m-d');
// 2017-05-15
// set a date with a Timezone
$date = new DateTime('2017-05-01', new DateTimeZone('Europe/Paris'));
echo "Europe/Paris " . $date->format('Y-m-d H:i:sP') . "\n";
$date->setTimezone(new DateTimeZone('Australia/Sydney'));
echo "Australia/Sydney " . $date->format('Y-m-d H:i:sP') . "\n";
// Europe/Paris 2017-05-01 00:00:00+02:00
// Australia/Sydney 2017-05-01 08:00:00+10:00
// set a date with a Timezone in number of hours
$date = new DateTime('2017-05-01', new DateTimeZone('+02:00'));
echo "UTC + 2 hours " . $date->format('Y-m-d H:i:sP') . "\n";
// UTC + 2 hours 2017-05-01 00:00:00+02:00
$utcDate = new DateTime('2017-05-01', new DateTimeZone('UTC'));
echo "UTC date " . $utcDate->format('Y-m-d H:i:sP') . "\n";
// UTC date 2017-05-01 00:00:00+00:00
// today in Paris, let's try to get the location of the timezone
$dateInParis = new \DateTime('now', new \DateTimeZone('Europe/Paris'));
print_r($dateInParis->getTimezone()->getLocation());
/*Array (
[country_code] => FR
[latitude] => 48.86666
[longitude] => 2.33333
[comments] =>
)*/
// now if we received this date in string format
$dateInParisFromString = new \DateTime($dateInParis->format('Y-m-d H:i:sP'));
var_dump($dateInParisFromString->getTimezone()->getLocation());
// bool(false)
// today in Paris, let's try to get the location of the timezone
$dateInParis = new \DateTime('now', new \DateTimeZone('Europe/Paris'));
$dateInParisFromString = new \DateTime(
$dateInParis->format('Y-m-d H:i:s'),
$dateInParis->getTimezone()
);
print_r($dateInParisFromString->getTimezone()->getLocation());
/* Array (
[country_code] => FR
[latitude] => 48.86666
[longitude] => 2.33333
[comments] =>
)*/
// set a date Interval
$dateInterval = new DateInterval('P2Y4DT6H8M');
// equivalent to
$dateIntervalFromString = DateInterval::createFromDateString(
'2 year + 4 day + 6 hour + 8 minute'
);
echo $dateInterval->format('%y years, %d days and %h hours, %i minute');
// 2 years, 4 days and 6 hours, 8 minute
echo $dateIntervalFromString->format('%y years, %d days and %h hours, %i minute');
// 2 years, 4 days and 6 hours, 8 minute
Request : Get the last half week, meaning from Monday to Wednesday or from Thursday to Sunday
// If today is between Monday to Wednesday,
// We want to get dates from last Thursday to last Sunday
$today = new DateTime();
// format N indicate the day number, Monday = 1, Tuesday = 2, etc...
if ($today->format('N') < 4 ){
$startDate = new DateTime('Last Thursday');
$endDate = new DateTime('Last Sunday');
}
// else, today is between Thursday to Sunday,
// we want to get dates from Last Monday to Last Wednesday
else {
$startDate = new DateTime('Last Monday');
$endDate = new DateTime('Last Wednesday');
}
Request : Get the last week, but if the week is between two months, take from the 1st day of this month
// We need to check If the Last Monday is in the last month
$lastMondayDate = new DateTime('Last Monday');
$lastDayOfLastMonthDate = new DateTime('Last Day of Last Month');
// if the last monday is indeed in the past month,
// we take the first day of this month
// else we take the last monday
if ($lastMondayDate->format('m') === $lastDayOfLastMonthDate->format('m')){
$startDate = new DateTime('First Day of This Month');
}
else{
$startDate = $lastMondayDate ;
}
// in both cases, end date is the Last Sunday
$endDate = new DateTime('Last Sunday');
Request : Get dates for a rolling 10 days period
// we set default dates, today is 2017-05-29
$endDate = new DateTime();
$startDate = new DateTime();
// substract 10 days with the object DateInterval
$startDate->sub(new DateInterval('P10D'));
// or you can use Date Interval with regular string
$startDate->sub(new DateInterval::createFromDateString('10 Days'));
// or you can use setDate if you don't like DateInterval
$startDate->setDate(
(int) $startDate->format('Y'),
(int) $startDate->format('m'),
(int) $startDate->format('d')-10
);
// startDate = 2017-05-19 , endDate = 2017-05-29
// Today is 2017-05-29
$date = new DateTime("first day of last month");
echo $date->format('Y-m-d') , ' => ';
$date->setDate(2013, 2, 3);
echo $date->format('Y-m-d');
// Today is : 2017-05-29
$date = new DateTime("first day of last month");
echo $date->format('Y-m-d') , ' => ';
$date->setDate(2013, 2, 3);
echo $date->format('Y-m-d');
// for 7.0.17 - 7.0.19, 7.1.3 - 7.2.0rc2
// 2017-04-01 => 2013-02-03
// for 5.6.0 - 5.6.30, hhvm-3.15.4 - 3.19.0, 7.0.0 - 7.0.16, 7.1.0 - 7.1.2
// 2017-04-01 => 2013-02-01
It's not the same behaviour depending of the PHP version
It's the same problem with some others String, exemple:
// Anoter Exemple, we create with Last day of this month
// and we set the new date on a Leap Year
$date = new DateTime("last day of this month");
echo $date->format('Y-m-d') , ' => ';
$date->setDate(2012, 2, 03);
echo $date->format('Y-m-d');
// for 7.0.17 - 7.0.19, 7.1.3 - 7.1.5
// 2017-05-31 => 2012-02-03
// for 5.6.0 - 5.6.30, hhvm-3.15.4 - 3.19.0, 7.0.0 - 7.0.16, 7.1.0 - 7.1.2
// 2017-05-31 => 2012-02-29 : it take in fact the last day of February 2012