56

I'm looking for the best way to get the first and the last day of a last month. I use them for make SQL queries to get stats of last month.

I think that this is the best way, more optimized but not more comprensive, anyone have another way to do the same?

    $month_ini = date("Y-m-d", mktime(0, 0, 0, date("m", strtotime("-1 month")), 1, date("Y", strtotime("-1 month"))));

    $month_end = date("Y-m-d", mktime(0, 0, 0, date("m", strtotime("-1 month")), date("t", strtotime("-1 month")), date("Y", strtotime("-1 month"))));

Thanks!!

aaronroman
  • 820
  • 1
  • 6
  • 10

6 Answers6

151

In PHP 5.3, you can use the DateTime class :

<?php

$month_ini = new DateTime("first day of last month");
$month_end = new DateTime("last day of last month");

echo $month_ini->format('Y-m-d'); // 2012-02-01
echo $month_end->format('Y-m-d'); // 2012-02-29
Phen
  • 2,313
  • 3
  • 18
  • 15
  • 1
    This ought to be the answer imho – LeonardChallis Jun 11 '13 at 22:00
  • 6
    This also works brilliantly with `strtotime()` if you want a timestamp. Like `strtotime('last day of last month')`. – Cobra_Fast Sep 11 '13 at 10:39
  • How would you do this if tou wanted first/last day of the month some date falls in? – Czechnology Jan 15 '14 at 17:36
  • 1
    You can use `new DateTime("first day of February 2012")` or `new DateTime("first day of 2012-02")` for instance. – Phen Jan 16 '14 at 06:25
  • 3
    Just beware, you don't get the beginning of the day on the first, but the server's current time. I like it, but don't use the whole object, make sure you format as @Phen suggests! – mimoralea Oct 08 '14 at 16:29
  • You can do `$month_ini->setTime(0, 0);` to reset the hours/minutes/seconds of the datetime instance. – Jonny Jun 01 '20 at 08:31
  • Single line options: `date('Y-m-d', strtotime('first day of last month'));` or `(new DateTime("first day of last month"))->format('Y-m-d');` – Maikon Matheus Jan 22 '21 at 02:51
67

Last day of the previous month:

date("Y-m-d", mktime(0, 0, 0, date("m"), 0));

First day of the previous month:

date("Y-m-d", mktime(0, 0, 0, date("m")-1, 1));
Case
  • 4,244
  • 5
  • 35
  • 53
user1064130
  • 729
  • 5
  • 3
  • 3
    Nice answer; if the current month is 01 (January) date() will decrement the year by one and wrap the month back round to 12, works great. Thanks! – jwbensley Mar 20 '12 at 16:50
  • This helped greatly, however there is no explanation or link to explanation of WHY it worked. ie. the 0 in the first statement is the last day because... (0 effectivly means -1 as there is no 0 day in any month and PHP takes it as the 1st - 1) – Tarquin Jun 29 '16 at 00:07
  • Caution: when using last day with time of 00:00:00 ... if you use this in a query the date-time will not include that day as it is at 0 time. To include the full day the time would need to be 23:59:59 ... alternative is to just use 0 time of the 1st of next month. – ChrisDeDavidMindflowAU Oct 28 '18 at 22:53
18

I use these in MySQL and PHP scripts, short and simple:

echo date('Y-m-d', strtotime('first day of last month'));
echo date('Y-m-d', strtotime('last day of last month'));

MySQL use example:

$query = $db->query("SELECT * FROM mytable WHERE 1 AND mydate >= '".date('Y-m-d', strtotime('first day of last month'))."'");
Tarik
  • 4,270
  • 38
  • 35
3

If you're doing this for the purpose of a MySQL query, have you considered using the MONTH function, e.g.

SELECT [whatever stats you're after] FROM table
WHERE MONTH(date_field) = 12 and YEAR(date_field) = 2011

This would get your stats for December. If you start to experience performance problems and the historical data doesn't change, you might want to denormalise the data into an aggregate table (rolled up by the smallest increment you need, e.g. daily/hourly/monthly etc).

liquorvicar
  • 6,081
  • 1
  • 16
  • 21
  • and what if there are rows from December 2010 and from December 2011? How do you distinguish them? – Bazzz Mar 16 '12 at 10:41
  • @Bazzz Doh! Good spot, have added the equivalent YEAR filter to it (although if you followed the link I provided this should have been pretty obvious!) – liquorvicar Mar 16 '12 at 10:44
-1

you can do this in MySQL:

WHERE `DateAndTime` >= '2012-02-01 00:00:00'
AND `DateAndTime` < '2012-03-01 00:00:00'
Bazzz
  • 26,427
  • 12
  • 52
  • 69
-2

let mysql deal with dates.

anything that is for the database to do, let it do.

like this:

mysql_query("set @last_day=last_day(now()-interval 1 month),@first_day=(@last_day-interval 1 month)+interval 1 day");
$result=mysql_query("select * from `table` where (`date` between @first_day and @last_day)");

the best is that this will work even if the year changes.

just remember to change the database timezone to match php.

Ismael Miguel
  • 4,185
  • 1
  • 31
  • 42