8

In Linux, I can get last month by using

date -d "last month" '+%Y%m'

or

date -d "1 month ago" '+%Y%m'

But say, today is 31st of March, if I run the command at top, it shows 201603, but I want to get last month regardless which day I'm in now; how can I do so?

I can achieve that by using workaround like get first day/last day of previous month, but I wonder is there any elegant way to do so?

 date -d "-$(date +%d) days" '+%Y%m'     #get last day of previous month
2

4 Answers 4

14

The usual wisdom is use the 15 of this month. Then subtract 1 month:

$ nowmonth=$(date +%Y-%m)
$ date -d "$nowmonth-15 last month" '+%Y%m'
201602
0
1

GNU date isn't particularly suited for arithmetic as you intend. That's one of the reasons I wrote dateutils.

Your example would boil down to:

$ dateadd today -1mo -f '%Y%m'
201603

And does the right thing on the 31st of March:

$ dateadd 2016-03-31 -1mo -f '%Y%m'
201602

Or what you imply by your comment (getting the last day of the previous month) regardless of the date today:

$ dateround --next today -31d
2016-03-31
$ dateround --next 2016-03-31 -31d
2016-02-29
1

My approach is always to aim to work with known reliable dates before applying date arithmetic. In this case I'd obtain the first day of the current month and then step back one day

date --date "$(date +%Y-%m-01) -1 day"

In certain timezones this might break if it's run during a leap second (61st second after 23:59 UTC) on a month boundary. We had one on 31st December 1999, but I've not looked to see whether the more recent ones were also on a month boundary.

1
  • This is the method that I like to use. As a bonus, it will also give you the last day of that month.
    – UncleCarl
    May 31, 2023 at 16:32
0

I had the same question few years ago and I got a really good answer about how "1 month ago" really works.

Quoting part of the answer from @rici

  • 1 month will subtract one from the month number, and then if the resulting date is not valid (February 30, for example), adjust it so that it is valid. So December 31 - 1 month is December 1, not a day in November, and March 31 - 1 month is March 3 (unless executed in a leap year).

For more information, please refer to the following answer

1
  • The unspoken issue is that, for (say) March 2019, "last month" maps 31 day numbers into 28 day numbers. It is not clear that mapping 29, 30, 31st all into 28th Feb is the right thing to do. It is also not a reversible mapping: should "next month" on 28 Feb map to 28th March? For accounting purposes, last day of Feb should probably map to last day of March. Best not to mention ISO week and day numbering, then. Jun 18, 2020 at 16:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .