Find Difference Between Two Dates C - c

I am trying to take one date away from another in C and find the difference between them in days. However, this is much more complicated than it first appeared to me as I obviously have to allow for differing days in different years due to leap years and a differing numbers of days depending on which month it is. I did try to use time.h but I do not think that it allows for leap years.
Currently my data is stored as integers in an array, for example, {2010, 5, 1, 2011, 6, 1}.
So could someone please post or point me towards an algorithm that will help me achieve this task? Thank you very much.

The standard library C Time Library contains structures and functions you want.
This header file contains definitions of functions to get and
manipulate date and time information.
Also check C date and time functions and C program days between two dates
EDIT:-
Try this:
int main()
{
int day1,mon1,year1,day2,mon2,year2;
int ref,dd1,dd2,i;
clrscr();
printf("Enter first date day, month, year\n");
scanf("%d%d%d",&day1,&mon1,&year1);
printf("Enter second date day, month, year\n");
scanf("%d%d%d",&day2,&mon2,&year2);
ref = year1;
if(year2<year1)
ref = year2;
dd1=0;
dd1=dater(mon1);
for(i=ref;i<year1;i++)
{
if(i%4==0)
dd1+=1;
}
dd1=dd1+day1+(year1-ref)*365;
dd2=0;
for(i=ref;i<year2;i++)
{
if(i%4==0)
dd2+=1;
}
dd2=dater(mon2)+dd2+day2+((year2-ref)*365);
printf("\n\n Difference between the two dates is %d days",abs(dd2-dd1));
getch();
}
int dater(x)
{ int y=0;
switch(x)
{
case 1: y=0; break;
case 2: y=31; break;
case 3: y=59; break;
case 4: y=90; break;
case 5: y=120;break;
case 6: y=151; break;
case 7: y=181; break;
case 8: y=212; break;
case 9: y=243; break;
case 10:y=273; break;
case 11:y=304; break;
case 12:y=334; break;
default: printf("Invalid Input\n\n\n\n"); exit(1);
}
return(y);
}
or using time.h try like this:
#include <stdio.h>
#include <time.h>
int main ()
{
struct tm start_date;
struct tm end_date;
time_t start_time, end_time;
double seconds;
start_date.tm_hour = 0; start_date.tm_min = 0; start_date.tm_sec = 0;
start_date.tm_mon = 10; start_date.tm_mday = 15; start_date.tm_year = 113;
end_date.tm_hour = 0; end_date.tm_min = 0; end_date.tm_sec = 0;
end_date.tm_mon = 10; end_date.tm_mday = 20; end_date.tm_year = 113;
start_time = mktime(&start_date);
end_time = mktime(&end_date);
seconds = difftime(end_time, start_time);
printf ("%.f seconds difference\n", seconds);
return 0;
}

Algo:
Convert dates to struct tm.
Convert struct tm to time_t.
Take the difference between the time_ts. It yields the difference between dates in seconds.
Divide the difference in seconds by 86400 to convert it to days.

/* This function calculates the differance between two dates, passes 6 parameters date-month-year of first date and date-month-year of second date and prints the difference in date-weeks-year format */
void Date::subtract(int firstDate, int firstMonth, int firstYear,int secondDate, int secondMonth, int secondYear)
{
/*check the dates are valid or not */
if(isDateValid(firstDate,firstMonth,firstYear) && isDateValid(secondDate,secondMonth,secondYear) )
{
firstMonth = (firstMonth + 9) % 12;
firstYear = firstYear - firstMonth / 10;
FirstNoOfDays = 365 * firstYear + firstYear/4 - firstYear/100 + firstYear/400 + (firstMonth * 306 + 5) /10 + ( firstDate - 1 );
secondMonth = (secondMonth + 9) % 12;
secondYear = secondYear - secondMonth / 10;
SecondNoOfDays = 365 * secondYear + secondYear/4 - secondYear/100 + secondYear/400 + (secondMonth * 306 + 5) /10 + ( secondDate - 1 );
dayDifference = abs(FirstNoOfDays - SecondNoOfDays); /* uses absolute if the first date is smaller so it wont give negative number */
years = dayDifference / 365;
weeks = (dayDifference % 365)/7;
days = (dayDifference % 365) % 7;
cout<<years<<" years "<<weeks<<" weeks "<<days<< " days"<<endl;
}
else
{
cout<<"Invalid Date"<<endl;
}
}

Related

A bit of help making an ordinal clock conversion

Currently, I have an assignment to make a piece of code that asks for the user's input before converting it to an ordinal clock, as well as an exception in the case of a leap year. The only issue is that I don't know what I'm doing in the case of putting arrays in functions.
/*The purpose of this program is to make the user enter a date and return the info as ordinal*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#define MAXDAYSINMONTH 12 /*Define maximums for dates*/
#define MAXDAYS 365
int main()
{
void findDate(int[], int *, int *); /*Prototype*/
int daysInMonth[MAXDAYSINMONTH]; /*Variables for function*/
int days, months, year, dayTest; /*Variables for user*/
printf("This Program will ask you for the date\n");
printf("Please enter the Day: "); /*Get User input*/
scanf("%d", &days);
printf("\nPlease enter the Month: ");
scanf("%d", &months);
printf("\nPlease enter the Year: ");
scanf("%d", &year);
findDate(days, months, &dayTest);/*call the function*/
/**
* Input: Actual Date
* Process: Conversion
* Output: Ordinal Date
*/
printf("The ordinal date for the date entered is: ", dayTest);/*Get Output*/
if (year / 4 == 0) { /*Look for Leap Year*/
if (dayTest > 59) {
dayTest = dayTest + 1;
}
printf("This date is a leap year");
}
else
printf("This date is not a leap year");
return 0;
}
/*Convert Regular Date to Ordinal*/
void findDate(int days, int months, int* dayTest, int daysInMonths[]) {
int daysInMonth[MAXDAYSINMONTH], dayTest; /*Variables for function*/
daysInMonth[0] = 31;
daysInMonth[1] = 28;
daysInMonth[2] = 31;
daysInMonth[3] = 30;
daysInMonth[4] = 31;
daysInMonth[5] = 30;
daysInMonth[6] = 31;
daysInMonth[7] = 31;
daysInMonth[8] = 30;
daysInMonth[9] = 31;
daysInMonth[10] = 30;
daysInMonth[11] = 31;
if (months > 31) {
*dayTestaddr = days + daysInMonth;
}
}
New code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#define MAXDAYSINMONTH 12 /*Define maximums for dates*/
#define MAXDAYS 365
void findDate(int days, int months, int* dayTest, int daysInMonths[]); /*Prototype*/
int main()
{
int daysInMonth[MAXDAYSINMONTH]; /*Variables for function*/
int days, months, year, dayTest; /*Variables for user*/
printf("This Program will ask you for the date\n");
printf("Please enter the Day: "); /*Get User input*/
scanf("%d", &days);
printf("\nPlease enter the Month: ");
scanf("%d", &months);
months = months - 1;
printf("\nPlease enter the Year: ");
scanf("%d", &year);
findDate(days, months, &dayTest, daysInMonth); /*call the function*/
/**
* Input: Actual Date
* Process: Conversion
* Output: Ordinal Date
*/
printf("The ordinal date for the date entered is: %d%d", year, dayTest);/*Get Output*/
if (year % 4 == 0) { /*Look for Leap Year*/
if (dayTest > 59) {
dayTest = dayTest + 1;
}
printf("\nThis date is a leap year");
}
else
printf("\nThis date is not a leap year");
return 0;
}
/*Convert Regular Date to Ordinal*/
void findDate(int days, int months, int* dayTest, int daysInMonths[]) {
daysInMonths[0] = 31;
daysInMonths[1] = 28;
daysInMonths[2] = 31;
daysInMonths[3] = 30;
daysInMonths[4] = 31;
daysInMonths[5] = 30;
daysInMonths[6] = 31;
daysInMonths[7] = 31;
daysInMonths[8] = 30;
daysInMonths[9] = 31;
daysInMonths[10] = 30;
daysInMonths[11] = 31;
if (months > 11 || months < 0)
{
// Illegal call
printf("Your month is over 12 or under 0, try again\n");
}
if (months == 0) {
*dayTest = days;
}
else
*dayTest = days + (daysInMonths[months] - daysInMonths[1]);
}
I'm just saving this so my progress can be more apparent, I do think I have a general handle, but I still need to keep going forward in regards to making an ordinal date in the format of YYYY-DDD. Help would be appreciated, and thank you.
The declarations of findDate are inconsistent and the prototype should be placed before main.
Your prototype:
void findDate(int[], int *, int *); /*Prototype*/
Your call:
findDate(days, months, &dayTest);
^ ^
| Not an int*
Not an array
Your definition:
void findDate(int days, int months, int* dayTest, int daysInMonths[])
Here you have 4 parameters but previously you only had 3. Also the individual parameter doesn't match previously definitions.
You need to fix this inconsistency.
Before main put:
void findDate(int days, int months, int* dayTest, int daysInMonths[]);
In main call it like:
findDate(days, months, &dayTest, daysInMonth);
And don't redefine variables like daysInMonth and dayTest in the function body. Simply do:
void findDate(int days, int months, int* dayTest, int daysInMonths[]) {
daysInMonth[0] = 31;
daysInMonth[1] = 28;
daysInMonth[2] = 31;
daysInMonth[3] = 30;
daysInMonth[4] = 31;
daysInMonth[5] = 30;
daysInMonth[6] = 31;
daysInMonth[7] = 31;
daysInMonth[8] = 30;
daysInMonth[9] = 31;
daysInMonth[10] = 30;
daysInMonth[11] = 31;
if (months >= 12 || months < 0)
{
// Illegal call
.. error handling ..
}
*dayTest = days + daysInMonth[months];
}
That said, why have the daysInMonths array as a variable that you fill every time you call the function? It's a waste of CPU cycles. Instead make it a global constant.
So before main do:
const int daysInMonth[] = {31, 28, 31, 30, ....};
then you don't need to pass the array at all and your function get much simpler:
void findDate(int days, int months, int* dayTest) {
if (months >= 12 || months < 0)
{
// Illegal call
.. error handling ..
}
*dayTest = days + daysInMonth[months];
}
or simplify further by using a return value instead of a pointer:
int findDate(int days, int months) {
assert(months >= 0 && months < 12);
return days + daysInMonth[months];
}
and call it like:
dayTest = findDate(days, months);
Much simpler... no pointers, no arrays to be passed to the function.
Final note... Array index starts from zero but your user will probably input 1 for january. So you have an inconsistency that must be handled.

Calculate the end date from start date and number of days in C

for the past few hours I've been trying to figure out how to write a programme in C to calculate the end date based on the start date and number of days. (I haven't found the forum for this exact problem, yet).
So let's say you input 27/1/2021 as the starting date and then 380 days. The programme should now calculate and show you the end date 11/2/2022.
I don't know how to move forward, the help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
int day, month, year, numberDays;
int leapYear(int year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}
int monthYear[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main(void) {
printf("Enter starting date: ");
scanf("%d %d %d", &day, &month, &year);
printf("Enter number of days: ");
scanf("%d", &numberDays);
leapYear(year);
int wholeYears, rest;
if (leapYear(year)) {
wholeYears = numberDays / 366;
rest = numberDays % 366;
}
else {
wholeYears = numberDays / 365;
rest = numberDays % 365;
}
int resultYears = year + wholeYears;
int midDays = day + rest;
int resultMonths;
return 0;
}
I can't move any further. I'd need help.
So let's say you input 27/1/2021 as the starting date and then 380 days. The programme should now calculate and show you the end date 11/2/2022.
An easy approach is to use mktime() to bring a date into its standard range.
#include <stdio.h>
#include <time.h>
int main(void) {
struct tm start = {.tm_year = 2021 - 1900, .tm_mon = 1 - 1, .tm_mday = 27,
.tm_hour = 12}; // Midday to avoid DST issues.
start.tm_mday += 380;
printf("%d/%d/%d\n", start.tm_mday, start.tm_mon + 1, start.tm_year + 1900);
time_t t = mktime(&start);
printf("%d/%d/%d %s\n", start.tm_mday, start.tm_mon + 1, start.tm_year + 1900,
t == -1 ? "failed" : "OK");
}
Output
407/1/2021
11/2/2022 OK
Otherwise with discrete code, one is effectively re-writing the year/month/day portion of mktime().
I don't know how to move forward, the help would be appreciated.
Add the 380 to d of y, m, d. Maybe add some value to m in other cases. Then perform basic range reductions. There are 12 months to every year. Month range [1...12]. There are 365*400 + 97 days every 400 years. Day of the month is at least 1.
Last step is to handle a day outside the month range.
A simply, though inefficient, approach: test if the data is more than the days in that month. If so subtract the days in that month and advance to the next month.
I left out some code details as OP's goal is some ideas to move forward.
#define DAYSPER400YEARS (365 * 400 + 97)
#define JANUARY 1
#define FEBRUARY 2
#define DECEMBER 12
#define MONTHPERYEAR 12
static int is_leap_year(long long year) {
// If not divisible by 4 ...
// If not divisible by 100 ...
// If not divisible by 400 ...
}
static int days_per_month(long long year, int month) {
static const signed char dpm[] = { 0, //
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month != FEBRUARY) {
return ....;
}
return .... + is_leap_year(year);
}
/*
* Bring a date into it primary range.
* https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
* The year, month, day may be any value INT_MIN ... INT_MAX.
* Return error flag.
*/
bool ymd_to_primary_range(int *year, int *month, int *day) {
long long y = *year;
y += *month / 12;
*month %= 12; // month now in -11 to 11 range
while (*month < JANUARY) {
*month += MONTHPERYEAR;
year--;
}
y += (*day / DAYSPER400YEARS) * 400;
*day %= DAYSPER400YEARS;
while (*day < 1) {
*day += DAYSPER400YEARS;
y -= 400;
}
int dpm;
while (*day > (dpm = days_per_month(y, *month))) {
*day -= dpm;
(*month)++;
if (*month > ...) {
*month -= ....;
y++;
}
}
if (y < INT_MIN) {
*year = INT_MIN;
return true;
}
if (y > INT_MAX) {
*year = INT_MAX;
return true;
}
*year = (int) y;
return false;
}
Smaple
int main(void) {
int y = 2021;
int m = 1;
int d = 27;
d += 380;
printf("Error: %d\n", ymd_to_primary_range(&y, &m, &d));
printf("Date (dmy): %2d/%02d/%04d\n", d, m, y);
}
Output
Error: 0
Date (dmy): 11/02/2022

Calculate datetime difference in C

I need a function that can calculate the difference between two datetime (year, month, day, hours, minute, seconds). and then return the difference in the same format.
int main (){
struct datetime dt_from;
init_datetime(&dt_from, 1995, 9, 15, 10, 40, 15);
struct datetime dt_to;
init_datetime(&dt_to, 2004, 6, 15, 10, 40, 20);
struct datetime dt_res;
datetime_diff(&dt_from, &dt_to, &dt_res);
return 0;
}
void datetime_diff(struct datetime *dt_from, struct datetime *dt_to
, struct datetime *dt_res) {
//What can I do here to calculate the difference, and get it in the dt_res?
}
Please have a look and try this example which uses time.h and should be portable. It calculates the difference in days between the dates in your question. You can change the program a little so that it works the way you want.
#include <stdio.h>
#include <time.h>
#include <math.h>
int main() {
time_t start_daylight, start_standard, end_daylight, end_standard;;
struct tm start_date = {0};
struct tm end_date = {0};
double diff;
printf("Start date: ");
scanf("%d %d %d", &start_date.tm_mday, &start_date.tm_mon, &start_date.tm_year);
printf("End date: ");
scanf("%d %d %d", &end_date.tm_mday, &end_date.tm_mon, &end_date.tm_year);
/* first with standard time */
start_date.tm_isdst = 0;
end_date.tm_isdst = 0;
start_standard = mktime(&start_date);
end_standard = mktime(&end_date);
diff = difftime(end_standard, start_standard);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
/* now with daylight time */
start_date.tm_isdst = 1;
end_date.tm_isdst = 1;
start_daylight = mktime(&start_date);
end_daylight = mktime(&end_date);
diff = difftime(end_daylight, start_daylight);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
return 0;
}
Test
Start date: 15 9 1995
End date: 15 6 2004
3195 days difference
Or even simpler for non-interactive code and with standard or daylight savings time:
#include <stdio.h>
#include <time.h>
#include <math.h>
int main()
{
time_t start_daylight, start_standard, end_daylight, end_standard;;
struct tm start_date = {0};
struct tm end_date = {0};
double diff;
start_date.tm_year = 1995;
start_date.tm_mon = 9;
start_date.tm_mday = 15;
start_date.tm_hour = 10;
start_date.tm_min = 40;
start_date.tm_sec = 15;
end_date.tm_mday = 15;
end_date.tm_mon = 6;
end_date.tm_year = 2004;
end_date.tm_hour = 10;
end_date.tm_min = 40;
end_date.tm_sec = 20;
/* first with standard time */
start_date.tm_isdst = 0;
end_date.tm_isdst = 0;
start_standard = mktime(&start_date);
end_standard = mktime(&end_date);
diff = difftime(end_standard, start_standard);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
/* now with daylight time */
start_date.tm_isdst = 1;
end_date.tm_isdst = 1;
start_daylight = mktime(&start_date);
end_daylight = mktime(&end_date);
diff = difftime(end_daylight, start_daylight);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
return 0;
}
Here is the basic idea:
Convert your datetime into an integral type (preferable long long or unsigned long long) which represents your datetime value as it's smallest unit (second in your case). How to achieve that? Easy transform the single values into seconds and add everything together. (seconds + minutes * 60 + hours * 3600 ...)
Do this for both values and then subtract the integer values.
Now convert the single integer value, the time difference, back to a datetime. How? Start with the biggest unit (years) and divide the difference by the amount of seconds within one year (60 * 60 * 24 * 365). Now you know how many years are in between your two datetimes. Take the rest and divide it by the amount of seconds per month, and so on...
(Obviously I ignored everything rather complicated, like daylight saving time for example)
However I would highly recommend using struct tm from time.h as mentioned in the comments. It is portable and you can use difftime.

Calculate time in C language

I am trying to calculate time in C language and i have the following program:
#include <stdio.h>
#include <time.h>
int main(void) {
int hours, minutes;
double diff;
time_t end, start;
struct tm times;
times.tm_sec = 0;
times.tm_min = 0;
times.tm_hour = 0;
times.tm_mday = 1;
times.tm_mon = 0;
times.tm_year = 70;
times.tm_wday = 4;
times.tm_yday = 0;
time_t ltt;
time(&ltt);
struct tm *ptm = localtime(&ltt);
times.tm_isdst = ptm->tm_isdst;
printf("Start time (HH:MM): ");
if((scanf("%d:%d", &times.tm_hour, &times.tm_min)) != 2){
return 1;
}
start = mktime(&times);
printf("End time (HH:MM): ");
if((scanf("%d:%d", &times.tm_hour, &times.tm_min)) != 2){
return 1;
}
end = mktime(&times);
diff = difftime(end, start);
hours = (int) diff / 3600;
minutes = (int) diff % 3600 / 60;
printf("The difference is %d:%d.\n", hours, minutes);
return 0;
}
The program works almost ok:
Output 1:
./program
Start time (HH:MM): 05:40
End time (HH:MM): 14:00
The difference is 8:20.
Output 2:
./program
Start time (HH:MM): 14:00
End time (HH:MM): 22:20
The difference is 8:20.
Output 3:
/program
Start time (HH:MM): 22:20
End time (HH:MM): 05:40
The difference is -16:-40.
As you can see, I got -16:-40 instead of 7:20.
I cannot figure out how to fix this.
If end is after midnight and start before, add 24 hours to the end value:
if( end < start )
{
end += 24 * 60 * 60 ;
}
diff = difftime(end, start);
Note too that all the code related to mktime and tm struct is unnecessary. Those are useful when you require time normalisation (for example if you set tm_hour to 25, mktime will generate a time_t value that is 0100hrs the following day, rolling over the month and year too if necessary), but here you are dealing with just time of day in hours and minutes, so you need just:
int hour ;
int minute ;
if((scanf("%d:%d", &hour, &minute)) != 2){
return 1;
}
start = (time_t)((hour * 60 + minute) * 60) ;
printf("End time (HH:MM): ");
if((scanf("%d:%d", &hour, &minute)) != 2){
return 1;
}
end = (time_t)((hour * 60 + minute) * 60) ;

C Program to find day of week given date

Is there a way to find out day of the week given date in just one line of C code?
For example
Given 19-05-2011(dd-mm-yyyy) gives me Thursday
As reported also by Wikipedia, in 1990 Michael Keith and Tom Craver published an expression to minimise the number of keystrokes needed to enter a self-contained function for converting a Gregorian date into a numerical day of the week.
The expression does preserve neither y nor d, and returns a zero-based index representing the day, starting with Sunday, i.e. if the day is Monday the expression returns 1.
A code example which uses the expression follows:
int d = 15 ; //Day 1-31
int m = 5 ; //Month 1-12`
int y = 2013 ; //Year 2013`
int weekday = (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7;
The expression uses the comma operator, as discussed in this answer.
Enjoy! ;-)
A one-liner is unlikely, but the strptime function can be used to parse your date format and the struct tm argument can be queried for its tm_wday member on systems that modify those fields automatically (e.g. some glibc implementations).
int get_weekday(char * str) {
struct tm tm;
memset((void *) &tm, 0, sizeof(tm));
if (strptime(str, "%d-%m-%Y", &tm) != NULL) {
time_t t = mktime(&tm);
if (t >= 0) {
return localtime(&t)->tm_wday; // Sunday=0, Monday=1, etc.
}
}
return -1;
}
Or you could encode these rules to do some arithmetic in a really long single line:
1 Jan 1900 was a Monday.
Thirty days has September, April, June and November; all the rest have thirty-one, saving February alone, which has twenty-eight, rain or shine, and on leap years, twenty-nine.
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
EDIT: note that this solution only works for dates after the UNIX epoch (1970-01-01T00:00:00Z).
Here's a C99 version based on wikipedia's article about Julian Day
#include <stdio.h>
const char *wd(int year, int month, int day) {
/* using C99 compound literals in a single line: notice the splicing */
return ((const char *[]) \
{"Monday", "Tuesday", "Wednesday", \
"Thursday", "Friday", "Saturday", "Sunday"})[ \
( \
day \
+ ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) \
+ (365 * (year + 4800 - ((14 - month) / 12))) \
+ ((year + 4800 - ((14 - month) / 12)) / 4) \
- ((year + 4800 - ((14 - month) / 12)) / 100) \
+ ((year + 4800 - ((14 - month) / 12)) / 400) \
- 32045 \
) % 7];
}
int main(void) {
printf("%d-%02d-%02d: %s\n", 2011, 5, 19, wd(2011, 5, 19));
printf("%d-%02d-%02d: %s\n", 2038, 1, 19, wd(2038, 1, 19));
return 0;
}
By removing the splicing and spaces from the return line in the wd() function, it can be compacted to a 286 character single line :)
This is my implementation. It's very short and includes error checking. If you want dates before 01-01-1900, you could easily change the anchor to the starting date of the Gregorian calendar.
#include <stdio.h>
int main(int argv, char** arv) {
int month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char* day[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int d, m, y, i;
printf("Fill in a date after 01-01-1900 as dd-mm-yyyy: ");
scanf("%d-%d-%d", &d, &m, &y);
// correction for leap year
if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
month[1] = 29;
if (y < 1900 || m < 1 || m > 12 || d < 1 || d > month[m - 1]) {
printf("This is an invalid date.\n");
return 1;
}
for (i = 1900; i < y; i++)
if (i % 4 == 0 && (i % 100 != 0 || i % 400 == 0))
d += 366;
else
d += 365;
for (i = 0; i < m - 1; i++)
d += month[i];
printf("This is a %s.\n", day[d % 7]);
return 0;
}
The answer I came up with:
const int16_t TM_MON_DAYS_ACCU[12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
int tm_is_leap_year(unsigned year) {
return ((year & 3) == 0) && ((year % 400 == 0) || (year % 100 != 0));
}
// The "Doomsday" the the day of the week of March 0th,
// i.e the last day of February.
// In common years January 3rd has the same day of the week,
// and on leap years it's January 4th.
int tm_doomsday(int year) {
int result;
result = TM_WDAY_TUE;
result += year; // I optimized the calculation a bit:
result += year >>= 2; // result += year / 4
result -= year /= 25; // result += year / 100
result += year >>= 2; // result += year / 400
return result;
}
void tm_get_wyday(int year, int mon, int mday, int *wday, int *yday) {
int is_leap_year = tm_is_leap_year(year);
// How many days passed since Jan 1st?
*yday = TM_MON_DAYS_ACCU[mon] + mday + (mon <= TM_MON_FEB ? 0 : is_leap_year) - 1;
// Which day of the week was Jan 1st of the given year?
int jan1 = tm_doomsday(year) - 2 - is_leap_year;
// Now just add these two values.
*wday = (jan1 + *yday) % 7;
}
with these defines (matching struct tm of time.h):
#define TM_WDAY_SUN 0
#define TM_WDAY_MON 1
#define TM_WDAY_TUE 2
#define TM_WDAY_WED 3
#define TM_WDAY_THU 4
#define TM_WDAY_FRI 5
#define TM_WDAY_SAT 6
#define TM_MON_JAN 0
#define TM_MON_FEB 1
#define TM_MON_MAR 2
#define TM_MON_APR 3
#define TM_MON_MAY 4
#define TM_MON_JUN 5
#define TM_MON_JUL 6
#define TM_MON_AUG 7
#define TM_MON_SEP 8
#define TM_MON_OCT 9
#define TM_MON_NOV 10
#define TM_MON_DEC 11
#include<stdio.h>
#include<math.h>
#include<conio.h>
int fm(int date, int month, int year) {
int fmonth, leap;
if ((year % 100 == 0) && (year % 400 != 0))
leap = 0;
else if (year % 4 == 0)
leap = 1;
else
leap = 0;
fmonth = 3 + (2 - leap) * ((month + 2) / (2 * month))+ (5 * month + month / 9) / 2;
fmonth = fmonth % 7;
return fmonth;
}
int day_of_week(int date, int month, int year) {
int dayOfWeek;
int YY = year % 100;
int century = year / 100;
printf("\nDate: %d/%d/%d \n", date, month, year);
dayOfWeek = 1.25 * YY + fm(date, month, year) + date - 2 * (century % 4);
//remainder on division by 7
dayOfWeek = dayOfWeek % 7;
switch (dayOfWeek) {
case 0:
printf("weekday = Saturday");
break;
case 1:
printf("weekday = Sunday");
break;
case 2:
printf("weekday = Monday");
break;
case 3:
printf("weekday = Tuesday");
break;
case 4:
printf("weekday = Wednesday");
break;
case 5:
printf("weekday = Thursday");
break;
case 6:
printf("weekday = Friday");
break;
default:
printf("Incorrect data");
}
return 0;
}
int main() {
int date, month, year;
printf("\nEnter the year ");
scanf("%d", &year);
printf("\nEnter the month ");
scanf("%d", &month);
printf("\nEnter the date ");
scanf("%d", &date);
day_of_week(date, month, year);
return 0;
}
OUTPUT:
Enter the year 2012
Enter the month 02
Enter the date 29
Date: 29/2/2012
weekday = Wednesday
This is question 20.31 in the C FAQ list. It lists three answers, two of which are amenable to one-liners.
Modified Zeller's congruence: j = y/100; k = y%100; dow = (d + 26 * (m + 1) / 10 + k + k/4 + j/4 + 5*j) % 7;
Tomohiko Sakamoto's method: static int t[] = {0,3,2,5,0,3,5,1,4,6,2,4}; y -= m < 3; dow = (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
There's a further condensation of Sakamoto's method using an ASCII string instead of the t array: dow = (y + y/4 - y/100 + y/400 + "-bed=pen+mad."[m] + d) % 7;
The basic idea underlying all of these methods is the same: boil the date down to a monotonically-increasing sequence of day numbers (taking month lengths and leap years into account), then reduce that day number modulo 7.
I think you can find that in glib:
http://developer.gnome.org/glib/unstable/glib-Date-and-Time-Functions.html#g-date-get-day
Regards
#include<stdio.h>
static char day_tab[2][13] = {
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}
};
int main()
{
int year,month;
scanf("%d%d%d",&year,&month,&day);
printf("%d\n",day_of_year(year,month,day));
return 0;
}
int day_of_year(int year ,int month,int day)
{
int i,leap;
leap = year%4 == 0 && year%100 != 0 || year%400 == 0;
if(month < 1 || month >12)
return -1;
if (day <1 || day > day_tab[leap][month])
return -1;
for(i= 1;i<month ; i++)
{
day += day_tab[leap][year];
}
return day;
}
/*
Program to calculate the day on a given date by User
*/
#include<stdio.h>
#include<conio.h>
#include<process.h>
void main()
{
int dd=0,mm=0,i=0,yy=0,odd1=0,todd=0;//variable declaration for inputing the date
int remyr=0,remyr1=0,lyrs=0,oyrs=0,cyr=0,upyr=0,leap=0;//variable declaration for calculation of odd days
int montharr[12]={31,28,31,30,31,30,31,31,30,31,30,31};//array of month days
clrscr();
printf("Enter the date as DD-MM-YY for which you want to know the day\t:");
scanf("%d%d%d",&dd,&mm,&yy); //input the date
/*
check out correct date or not?
*/
if(yy%100==0)
{
if(yy%400==0)
{
//its the leap year
leap=1;
if(dd>29&&mm==2)
{
printf("You have entered wrong date");
getch();
exit(0);
}
}
else if(dd>28&&mm==2)
{
//not the leap year
printf("You have entered wrong date");
getch();
exit(0);
}
}
else if(yy%4==0)
{
//again leap year
leap=1;
if(dd>29&mm==2)
{
printf("You have entered wrong date");
getch();
exit(0);
}
}
else if(dd>28&&mm==2)
{
//not the leap year
printf("You have entered wrong date");
getch();
exit(0);
}
//if the leap year feb month contains 29 days
if(leap==1)
{
montharr[1]=29;
}
//check date,month,year should not be beyond the limits
if((mm>12)||(dd>31)|| (yy>5000))
{
printf("Your date is wrong");
getch();
exit(0);
}
//odd months should not contain more than 31 days
if((dd>31 && (mm == 1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12)))
{
printf("Your date is wrong");
getch();
exit(0);
}
//even months should not contains more than 30 days
if((dd>30 && (mm == 4||mm==6||mm==9||mm==11)))
{
printf("Your date is wrong");
getch();
exit(0);
}
//logic to calculate odd days.....
printf("\nYou have entered date: %d-%d-%d ",dd,mm,yy);
remyr1=yy-1;
remyr=remyr1%400;
cyr=remyr/100;
if(remyr==0)
{
oyrs=0;
}
else if(cyr==0 && remyr>0)
{
oyrs=0;
}
else if(cyr==1)
{
oyrs=5;
}
else if(cyr==2)
{
oyrs=3;
}
else if(cyr==3)
{
oyrs=1;
}
upyr=remyr%100;
lyrs=upyr/4;
odd1=lyrs+upyr;
odd1=odd1%7;
odd1=odd1+oyrs;
for(i=0;i<mm-1;i++)
{
odd1=odd1+montharr[i];
}
todd=odd1+dd;
if(todd>7)
todd=todd%7; //total odd days gives the re quired day....
printf("\n\nThe day on %d-%d-%d :",dd,mm,yy);
if(todd==0)
printf("Sunday");
if(todd==1)
printf("Monday");
if(todd==2)
printf("Tuesday");
if(todd==3)
printf("Wednesday");
if(todd==4)
printf("Thrusday");
if(todd==5)
printf("Friday");
if(todd==6)
printf("Saturday");
getch();
}
For Day of Week, years 2000 - 2099.
uint8_t rtc_DayOfWeek(uint8_t year, uint8_t month, uint8_t day)
{
//static const uint8_t month_offset_table[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; // Typical table.
// Added 1 to Jan, Feb. Subtracted 1 from each instead of adding 6 in calc below.
static const uint8_t month_offset_table[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
// Year is 0 - 99, representing years 2000 - 2099
// Month starts at 0.
// Day starts at 1.
// Subtract 1 in calc for Jan, Feb, only in leap years.
// Subtracting 1 from year has the effect of subtracting 2 in leap years, subtracting 1 otherwise.
// Adding 1 for Jan, Feb in Month Table so calc ends up subtracting 1 for Jan, Feb, only in leap years.
// All of this complication to avoid the check if it is a leap year.
if (month < 2) {
year--;
}
// Century constant is 6. Subtract 1 from Month Table, so difference is 7.
// Sunday (0), Monday (1) ...
return (day + month_offset_table[month] + year + (year >> 2)) % 7;
} /* end rtc_DayOfWeek() */
This one works: I took January 2006 as a reference. (It is a Sunday)
int isLeapYear(int year) {
if(((year%4==0)&&(year%100!=0))||((year%400==0)))
return 1;
else
return 0;
}
int isDateValid(int dd,int mm,int yyyy) {
int isValid=-1;
if(mm<0||mm>12) {
isValid=-1;
}
else {
if((mm==1)||(mm==3)||(mm==5)||(mm==7)||(mm==8)||(mm==10)||(mm==12)) {
if((dd>0)&&(dd<=31))
isValid=1;
} else if((mm==4)||(mm==6)||(mm==9)||(mm==11)) {
if((dd>0)&&(dd<=30))
isValid=1;
} else {
if(isLeapYear(yyyy)){
if((dd>0)&&dd<30)
isValid=1;
} else {
if((dd>0)&&dd<29)
isValid=1;
}
}
}
return isValid;
}
int calculateDayOfWeek(int dd,int mm,int yyyy) {
if(isDateValid(dd,mm,yyyy)==-1) {
return -1;
}
int days=0;
int i;
for(i=yyyy-1;i>=2006;i--) {
days+=(365+isLeapYear(i));
}
printf("days after years is %d\n",days);
for(i=mm-1;i>0;i--) {
if((i==1)||(i==3)||(i==5)||(i==7)||(i==8)||(i==10)) {
days+=31;
}
else if((i==4)||(i==6)||(i==9)||(i==11)) {
days+=30;
} else {
days+= (28+isLeapYear(i));
}
}
printf("days after months is %d\n",days);
days+=dd;
printf("days after days is %d\n",days);
return ((days-1)%7);
}
Here is a simple code that I created in c that should fix your problem :
#include <conio.h>
int main()
{
int y,n,oy,ly,td,a,month,mon_,d,days,down,up; // oy==ordinary year, td=total days, d=date
printf("Enter the year,month,date: ");
scanf("%d%d%d",&y,&month,&d);
n= y-1; //here we subtracted one year because we have to find on a particular day of that year, so we will not count whole year.
oy= n%4;
if(oy==0) // for leap year
{
mon_= month-1;
down= mon_/2; //down means months containing 30 days.
up= mon_-down; // up means months containing 31 days.
if(mon_>=2)
{
days=(up*31)+((down-1)*30)+29+d; // here in down case one month will be of feb so we subtracted 1 and after that seperately
td= (oy*365)+(ly*366)+days; // added 29 days as it is the if block of leap year case.
}
if(mon_==1)
{
days=(up*31)+d;
td= (oy*365)+(ly*366)+days;
}
if(mon_==0)
{
days= d;
td= (oy*365)+(ly*366)+days;
}
}
else
{
mon_= month-1;
down= mon_/2;
up= mon_-down;
if(mon_>=2)
{
days=(up*31)+((down-1)*30)+28+d;
td= (oy*365)+(ly*366)+days;
}
if(mon_==1)
{
days=(up*31)+d;
td= (oy*365)+(ly*366)+days;
}
if(mon_==0)
{
days= d;
td= (oy*365)+(ly*366)+days;
}
}
ly= n/4;
a= td%7;
if(a==0)
printf("\nSunday");
if(a==1)
printf("\nMonday");
if(a==2)
printf("\nTuesday");
if(a==3)
printf("\nWednesday");
if(a==4)
printf("\nThursday");
if(a==5)
printf("\nFriday");
if(a==6)
printf("\nSaturday");
return 0;
}
I wrote a small function to do this in C inspired by Conway's doomsday algorithm.
It was written with 8-bit microcontrollers in mind and the "year" argument is a year from 0 to 99 only (representing 2000 to 2099). I wrote it to compile down nice and small on avr-gcc. It uses no lookup table (I got the code smaller without).
// day of week, Thomas Rutter
// y should be a year 0 to 99 (meaning 2000 to 2099)
// m and d are 1-based (1-12, 1-31)
// returns 0 = sunday, ..., 6 = saturday
uint8_t dayofweek(uint8_t y, uint8_t m, uint8_t d)
{
uint8_t x = y + 24 - (m < 3);
x = x + (x >> 2) + d - m;
if (m & 1)
x += (m & 8) ? 4 : 3;
if (m < 3)
x += 3;
return x % 7;
}
In my own version, the mod operator at the bottom was replaced with my own optimised code as the platform I was using has no MUL or DIV and I wanted it 1 to 7 instead of 0 to 6.
This could be adapted to work with other centuries or specify the year in full - I just didn't need to do so for my own use.
See strftime and %u or %w qualifiers
#include<stdio.h>
int main(void) {
int n,y;
int ly=0;
int mon;
printf("enter the date\n");
scanf("%d",&n);
printf("enter the month in integer\n");
scanf("%d",&mon);
mon=mon-1;
printf("enter year\n");
scanf("%d",&y);
int dayT;
dayT=n%7;
if((y%4==0&&y%100!=0)|(y%4==0&&y%100==0&&y%400==0))
{
ly=y;
printf("the given year is a leap year\n");
}
char a[12]={6,2,2,5,0,3,5,1,4,6,2,4};
if(ly!=0)
{
a[0]=5;
a[1]=1;
}
int m,p;
m=a[mon];
int i,j=0,t=1;
for(i=1600;i<=3000;i++)
{
i=i+99;
if(i<y)
{
if(t==1)
{
p=5;t++;
}
else if(t==2)
{
p=3;
t++;
}
else if(t==3)
{
p=1;
t++;
}
else
{
p=0;
t=1;
}
}}
int q,r,s;
q=y%100;
r=q%7;
s=q/4;
int yTerm;
yTerm=p+r+s;
int w=dayT+m+yTerm;
w=w%7;
if(w==0)
printf("SUNDAY");
else if(w==1)
printf("MONDAY");
else if(w==2)
printf("TUESDAY");
else if(w==3)
printf("WEDNESDAY");
else if(w==4)
printf("THURSDAY");
else if(w==5)
printf("FRIDAY");
else
printf("SATURDAY");
return 0;
}

Resources