0

I've got an issue which I can't find a solution. Or at least a "good" one. I want to find the last day of the month given a month and a year in C.

For example :

last_day(10, 2017) > 31
last_day(02, 2017) > 28
last_day(02, 2016) > 29
last_day(01, 2017) > 31
last_day(12, 2010) > 31

last_day(X, Y) > X is the month, Y the year

Here is my idea: Get the day on the month X + 1, of year Y. Remove 1 day from this date.

I would like to know if there is a better solution than that, since that will a make "lot" of operation for a "simple" thing.

Thanks.

Edit : https://ideone.com/sIISO1

#include <stdio.h>
#include <time.h>
#include <string.h>

int main(void) {
    struct tm tm;
    char out[256];

    memset(&tm, 0, sizeof(struct tm));

    tm.tm_mon = 1;
    tm.tm_mday = 0;

    strftime(out, 256, "%d-%m-%Y", &tm);

    printf("%s", out);

    return 0;
}

I've tested by using struct tm, and day = 0, in order to get the previous day but did not work

Rndp13
  • 1,094
  • 1
  • 21
  • 35
kaldoran
  • 845
  • 6
  • 19

1 Answers1

1

Ask point out in the commentary, I've complexify the problem way to much.

I have been inspired by what @Agnishom Chattopadhyay said in comment, which is get the date from a lookup table.

But I did make a function which did that

#include <stdio.h>

int days_in_month(int month, int year) {
    if ( year < 1582 ) return 0; /* Before this year the Gregorian Calendar was not define */  
    if ( month > 12 || month < 1 ) return 0;

    if (month == 4 || month == 6 || month == 9 || month == 11) return 30;
    else if (month == 2) return (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28);
    return 31;
}

int main() {
    printf("%d\n", days_in_month(10, 2017));    
    printf("%d\n", days_in_month(2, 2000));
    printf("%d\n", days_in_month(2, 1300)); // Does not work !
    printf("%d\n", days_in_month(2, 2018));
    printf("%d\n", days_in_month(2, 2016));
}

https://ideone.com/5OZ3pZ

kaldoran
  • 845
  • 6
  • 19
  • 1
    That's not a table, that's code. But still, it looks about right, except for using `long`, that's a rather weird choice. Plain `int` is certainly enough, and what I would expect. – unwind Oct 12 '17 at 08:14
  • I did edit my answer in order to use `int` instead of `long`. Thanks – kaldoran Oct 12 '17 at 08:16
  • 1
    Nice. Also, I will never understand the style that uses `()` with `return`, it's not a function and making it look like one makes it kind of look more like the opposite of what it is doing ("going down rather than up the callstack", so to speak), which I find super-confusing. But to each their own, I guess. – unwind Oct 12 '17 at 08:28
  • 2
    Well just to be honest with you, I'm against this style but I did write this code for my work and the coding rules said that you need to use `()` with `return`. I will edit my code in order to remove them [since It will probably confuse "new" user of C] – kaldoran Oct 12 '17 at 08:36
  • You should put a check on years, like the one on months: as is, this does not work for February 1300. – mouviciel Oct 12 '17 at 08:42
  • Well I've tested some few more version and none of them work for year 1300 sadly ( all the algorithm version failed ) [for example : https://ideone.com/stcOr7 ] – kaldoran Oct 12 '17 at 09:02
  • Your code is not correct for February. You need to do the year checks in the inverse order. `year % 4 === 0` will match when `year=100`; `year % 100 === 0` will match when `year=400` – Emil Vikström Oct 12 '17 at 09:07
  • ... and just like that you made the code completely unmaintainable :| – Emil Vikström Oct 12 '17 at 09:08
  • @EmilVikström Well I just copy the algorithm from wikipedia [and other answer on stackoverflow] but sadly their is some date that I does not work as mouviciel point out. Edit : I did find something usefull : https://stackoverflow.com/questions/3220163/how-to-find-leap-year-programatically-in-c#11595914 – kaldoran Oct 12 '17 at 09:10
  • @mouviciel at the end I did end up by adding a condition on the year since before 1582 you can't be sure of the algorithm. Thanks for pointing that out – kaldoran Oct 12 '17 at 09:22
  • 1
    Note that the leap year rules changed in continental Europe at various times. The UK and its colonies changed in 1752. Sweden had a fun time and managed to get it wrong, and one of the steps to fixing it was to have 30 February 1712 (IIRC the year). Russia didn’t change until after the October Revolution, which happened in November according to most of the world’s calendars. Running the calendars backwards (the Proleptic Gregorian calendar) is fraught. – Jonathan Leffler Oct 12 '17 at 09:48