I needed to convert the day number, that is, what day it is between 1 and 365, into a month and day without using Calendar / DateTime classes and such today, so I knocked up a few simple functions that work assuming it’s not a leap year (i.e. that February has 28 days).
Here they are if they’re of any use to you:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
int dateToDayNumber(int month, int day) { // Catch invalid input and return early if (month < 1 || month > 12 || day < 1 || day > 31) return 0; if (month == 1 ) return day; if (month == 2 ) return 31 + day; if (month == 3 ) return 59 + day; if (month == 4 ) return 90 + day; if (month == 5 ) return 120 + day; if (month == 6 ) return 151 + day; if (month == 7 ) return 181 + day; if (month == 8 ) return 212 + day; if (month == 9 ) return 243 + day; if (month == 10) return 273 + day; if (month == 11) return 304 + day; return 334 + day; } int dayNumberToMonth(int dayNumber) { // Catch invalid input and return early if (dayNumber < 1 || dayNumber > 365) return 0; if (dayNumber <= 31 ) return 1; // Jan if (dayNumber <= 59 ) return 2; // Feb if (dayNumber <= 90 ) return 3; // Mar if (dayNumber <= 120) return 4; // Apr if (dayNumber <= 151) return 5; // May if (dayNumber <= 181) return 6; // Jun if (dayNumber <= 212) return 7; // Jul if (dayNumber <= 243) return 8; // Aug if (dayNumber <= 273) return 9; // Sep if (dayNumber <= 304) return 10; // Oct if (dayNumber <= 334) return 11; // Nov return 12; // Dec } int dayNumberToDayOfMonth(int dayNumber) { // Catch invalid input and return early if (dayNumber < 1 || dayNumber > 365) return 0; if (dayNumber <= 31 ) return dayNumber; // Jan if (dayNumber <= 59 ) return dayNumber - 31; // Feb if (dayNumber <= 90 ) return dayNumber - 59; // Mar if (dayNumber <= 120) return dayNumber - 90; // Apr if (dayNumber <= 151) return dayNumber - 120; // May if (dayNumber <= 181) return dayNumber - 151; // Jun if (dayNumber <= 212) return dayNumber - 181; // Jul if (dayNumber <= 243) return dayNumber - 212; // Aug if (dayNumber <= 273) return dayNumber - 243; // Sep if (dayNumber <= 304) return dayNumber - 273; // Oct if (dayNumber <= 334) return dayNumber - 304; // Nov return dayNumber - 334; // Dec } |
A touch cheap, but it gets the job done.
Sorry, but this is not good. Please take a read of this:
https://alcor.concordia.ca/~gpkatch/gdate-method.html
Here’s an implementation of the algorithms described:
https://pastebin.com/X7XuzqTh
The code is not tested, and no error checking is performed. It’s just an implementation of the date algorithms to solve the problem you have listed.
Haha, that’s a very clever way of doing it. Thanks for pointing this out!
Also, thanks for the implementation link – very well done.
Update: In case the pastebin link expires or such, here is Mneumonic Carrier’s provided reference implementation:
You’re welcome! I thought it would be better posting my code in pastebin rather than the comments section here, as I wasn’t sure if code would be formatted correctly here.
Whenever working with dates, the first step is to convert that date into a “date number”. This isn’t actually that difficult, but most people don’t realize that a leap year is: “…every four years, except if the year is divisible by 100, but even then it’s still a leap year if it’s divisible by 400…”.
A clear understanding of the problem domain is essential (and sometimes it requires a little effort (i.e. reading) to understand the problem domain).
My CalcDateFromDayNum() method could be implemented in many different ways. I’m used a template function because it’s something I’m used to using for returning more complex data structures from a method (in this case, a string vector). However, a neater way to achieve this would be to pass an iterator to the string vector container instead, like so:
And then call it like this:
The advantage of doing it this way is it’s more versatile, as all containers have iterators (i.e. the previous implementation would only work with containers that support the push_back() method).
Of course, another way would be to simply return a stringvec (string vector), just like CalcDayAndMonth does:
Of course, you could always use a properly defined struct or class to hold the date type:
In which case your CalcDateFromDayNum() becomes:
and CalcDayAndMonth() becomes:
And inside your main() you do:
The latter (with the TDate struct) is problem much easier to read and understand (instead of relying on a stringvec).
Here’s the complete implementation using the TDate struct:
https://pastebin.com/iQFaUT9T
As an added bonus, it’s a trivial matter to find the “Day of Week”:
But now I’m just rambling…
Wow! A very comprehensive coverage of the matter – and orders of magnitude more thought than I’d put into it!
Outstanding work. I salute you, sir! =D