Reputation: 33
I'm trying to write a program in c that tells you how many days it is until Christmas. I've never worked with the time.h library before so I'm winging most of it. I can get the current time easy enough but my problem is that I'm not sure how to enter the information for Christmas day properly which messes up the difftime calculation. The code below is outputting a different number each time it's run but no matter what I try I can't get it working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t currentDate;
time (¤tDate);
struct tm * now;
now = localtime (¤tDate);
struct tm xmas;
xmas = *localtime(¤tDate);
xmas.tm_yday = 359;
double seconds = difftime(asctime(&xmas),asctime(&now));
double days=seconds/86400;
printf("%g days\n", days);
return 0;
}
Upvotes: 2
Views: 2150
Reputation: 852
You are on the right track, but difftime takes variables of type time_t as arguments. Therefore, the 'now' variable you used is not needed. The 'xmas' variable you have should be initialized in a slightly different way from how you initialized it. Then you can use mktime() on it to convert it to type time_t for use in difftime().
Note you can run/modify the following code in your browser for free in this coding sandbox: https://www.next.tech/projects/4d440a51b6c4/share?ref=1290eccd.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
double seconds, days;
time_t currentDate;
struct tm *xmas, today;
time (¤tDate);
today = *localtime(¤tDate);
xmas = localtime(¤tDate);
xmas->tm_mon = 11; // 0 == January, 11 == December
xmas->tm_mday = 25;
if (today.tm_mday > 25 && today.tm_mon == 11)
xmas->tm_year = today.tm_year + 1;
seconds = difftime(mktime(xmas),currentDate);
days = seconds/86400;
printf("%g days\n", days);
return 0;
}
Reference - http://www.cplusplus.com/reference/ctime/difftime/
Upvotes: 3
Reputation: 11
int days_before_christ_mass()
{
int months_day_size[] = {31,28,31,30,31,30,31,31,30,31,30,31};
int christ_mass_day = 25;
int months = 12;
int day = 26;
cout << "Month: " << months << endl;
cout << "Day: " << day << endl;
int zero_starter_month = months - 1;
if (zero_starter_month < 11) {
if (day <= months_day_size[zero_starter_month]) {
int daysSummation = abs(day - months_day_size[zero_starter_month]);
//cout << daysSummation << endl;
for (int i = zero_starter_month + 1; i < 11; i++)
daysSummation += months_day_size[i];
daysSummation = daysSummation + christ_mass_day;
//cout << daysSummation << endl;;
return daysSummation;
}
else {
cout << "No such day" << endl;
return -1;
}
}
else if (zero_starter_month == 11) {
if (day <= months_day_size[zero_starter_month]) {
if (day <= christ_mass_day) {
return christ_mass_day - day;
}
else {
int day_summation = abs(day - months_day_size[zero_starter_month]);
for (int i = 0; i < 11; i++)
day_summation += months_day_size[i];
day_summation += christ_mass_day;
return day_summation;
}
}
else {
cout << "No such day" << endl
return -1;
}
}
else {
cout << "There is no such month" << endl;
return -1;
}
}
this code works with positive int
day and month input because month and day could never be zero and negative.
Upvotes: 1
Reputation: 5525
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.
Upvotes: 0
Reputation: 8030
First of all, you should read the chapter about date and time on libc manual:
https://www.gnu.org/software/libc/manual/html_node/Date-and-Time.html
Date and time handling in C kinda sucks, so you need to understand the concepts well so that you don't get confused.
The main task is to call difftime, where the target time is christmas and the start time is the current time. Since difftime receives times in time_t format, we need both current time and christmas in time_t. For current time in time_t format, you may use the time() function. For converting a structured calendar time into time_t, you need mktime(). So the code ends up the following:
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t now;
time_t christmas;
struct tm tmp;
double seconds;
double days;
time(&now);
tmp.tm_sec = 0;
tmp.tm_min = 0;
tmp.tm_hour = 0;
tmp.tm_mday = 25;
tmp.tm_mon = 11; /* December == 11 */
tmp.tm_year = 116; /* 2016 */
tmp.tm_isdst = -1;
christmas = mktime(&tmp);
seconds = difftime(christmas, now);
days = seconds/86400;
printf("%g days untils christmas.\n", days);
return 0;
}
Upvotes: 1