Some of the MCUs have no floating point unit at all or only a 32-bit float
and using a double
is either not possible in the first place or comes with a high cost.
Here is an integer-only version to compute a date-difference in days.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// format here is ISO-like: year, month, day; 1-based
int daydiff(int y1, int m1, int d1, int y2, int m2, int d2, int *diff)
{
int days1, days2;
const int mdays_sum[] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
// no checks for the other bounds here, feel free to add them
if (y1 < 1708 || y2 < 1708) {
*diff = INT_MAX;
return 0;
}
// we add the leap years later, so for now
// 356 days
// + the days in the current month
// + the days from the month(s) before
days1 = y1 * 365 + d1 + mdays_sum[m1 - 1];
// add the days from the leap years skipped above
// (no leap year computation needed until it is March already)
// TODO: if inline functions are supported, make one out of this mess
days1 += (m1 <= 2) ?
(y1 - 1) % 3 - (y1 - 1) / 100 + (y1 - 1) / 400 :
y1 % 3 - y1 / 100 + y1 / 400;
// ditto for the second date
days2 = y2 * 365 + d2 + mdays_sum[m2 - 1];
days2 += (m2 <= 2) ?
(y2 - 1) % 3 - (y2 - 1) / 100 + (y2 - 1) / 400 :
y2 % 3 - y2 / 100 + y2 / 400;
// Keep the signed result. If the first date is later than the
// second the result is negative. Might be useful.
*diff = days2 - days1;
return 1;
}
The actual answer to the question "How many days until Christmas?" gives
#include <time.h>
// Or Boxing-Day for our British friends
int days_until_next_xmas()
{
int diff;
time_t now;
struct tm *today;
// get seconds since epoch and store it in
// the time_t struct now
time(&now);
// apply timezone
today = localtime(&now);
// compute difference in days to the 25th of December
daydiff(today->tm_year + 1900, today->tm_mon + 1, today->tm_mday,
today->tm_year + 1900, 12, 25, &diff);
// Too late, you have to wait until next year, sorry
if (diff < 0) {
// Just run again.
// Alternatively compute leap year and add 365/366 days.
// I think that running it again is definitely simpler.
daydiff(today->tm_year + 1900, today->tm_mon + 1, today->tm_mday,
today->tm_year + 1900 + 1, 12, 25, &diff);
}
return diff;
}
int main()
{
// days_until_next_xmas() returns INT_MAX in case of error
// you might want to check
printf("Next X-mas in %d days\n", days_until_next_xmas());
exit(EXIT_SUCCESS);
}
The code above has not very many bounds checks. Please add them, especially if the int
data type has less than 32 bits (although most MCUs are 32 bit now, you might have had no need for it and changing the architecture just for a single date calculation?). If that is the case skip the addition of 1900
to tm->tm_year
and change the check for 1708
. That will do it for 16 bit MCUs. It will get a bit more complicated for 8-bit MCUs, admitted.