Reputation: 191
I am trying to write a simple program in c++ that returns the day of the week for a given date.
The input format is day, month, year. I cannot get it to work with leap years. I tried subtracting one from the a
variable when the input year is a leap year, but the program just ends up crashing without an error message.
I would appreciate any suggestions, but please try to remain simple, I am still a beginner. Apologies for the stupid question, and please excuse my mistakes, this is the first time I post on this site.
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
int d;
int m;
int y;
string weekday(int d, int m, int y){
int LeapYears = (int) y/ 4;
long a = (y - LeapYears)*365 + LeapYears * 366;
if(m >= 2) a += 31;
if(m >= 3 && (int)y/4 == y/4) a += 29;
else if(m >= 3) a += 28;
if(m >= 4) a += 31;
if(m >= 5) a += 30;
if(m >= 6) a += 31;
if(m >= 7) a += 30;
if(m >= 8) a += 31;
if(m >= 9) a += 31;
if(m >= 10) a += 30;
if(m >= 11) a += 31;
if(m == 12) a += 30;
a += d;
int b = (a - 2) % 7;
switch (b){
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
case 7:
return "Sunday";
}
}
int main(){
cin >> d >> m >> y;
cout << weekday(d, m, y);
}
Upvotes: 18
Views: 79716
Reputation: 201
Your understanding of what constitutes a leap year is incorrect:
A leap year is every 4 years EXCEPT if it's divisible by 100, BUT even then it's still a leap year if it's divisible by 400.
A clear and concise explanation of how to calculate the "day number" (dn) can be found here.
Once you have the day number (dn), just perform a modulus 7. The result will be the day of week (dow).
Here's an example implementation (doesn't check if date is valid input):
#include <iostream>
#include <iomanip>
typedef unsigned long ul;
typedef unsigned int ui;
// ----------------------------------------------------------------------
// Given the year, month and day, return the day number.
// (see: https://alcor.concordia.ca/~gpkatch/gdate-method.html)
// ----------------------------------------------------------------------
ul CalcDayNumFromDate(ui y, ui m, ui d)
{
m = (m + 9) % 12;
y -= m / 10;
ul dn = 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + (d - 1);
return dn;
}
// ----------------------------------------------------------------------
// Given year, month, day, return the day of week (string).
// ----------------------------------------------------------------------
std::string CalcDayOfWeek(int y, ul m, ul d)
{
std::string day[] = {
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
"Monday",
"Tuesday"
};
ul dn = CalcDayNumFromDate(y, m, d);
return day[dn % 7];
}
// ----------------------------------------------------------------------
// Program entry point.
// ----------------------------------------------------------------------
int main(int argc, char **argv)
{
ui y = 2017, m = 8, d = 29; // 29th August, 2017.
std::string dow = CalcDayOfWeek(y, m, d);
std::cout << std::setfill('0') << std::setw(4) << y << "/";
std::cout << std::setfill('0') << std::setw(2) << m << "/";
std::cout << std::setfill('0') << std::setw(2) << d << ": ";
std::cout << dow << std::endl;
return 0;
}
Upvotes: 7
Reputation: 1
try using the CTime class
Exemple:
const CTime currTime = CTime::GetCurrentTime();
const int nWeekDay = currTime.GetDayOfWeek();
switch (nWeekDay)
{
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
case 7:
return "Sunday";
}
in the example above I'm using the current time, but you can do it differently, with the time you want example:
const CTime currTime = CTime(year,month, day, hours, minutes, seconds );
Upvotes: 0
Reputation: 219395
New answer for old question because the tools they are a changing...
The C++20 spec says the following will have identical functionality to the intention of the code in the question:
#include <chrono>
#include <format>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
year_month_day dmy;
cin >> parse("%d %m %Y", dmy);
cout << format("{:%A}", weekday{dmy}) << '\n';
}
One can experiment today with this syntax by using this free, open-source date/time library, except that the date objects are in namespace date
instead of namespace std::chrono
, and the syntax of the format string is slightly altered.
#include "date/date.h"
#include <iostream>
int
main()
{
using namespace std;
using namespace date;
year_month_day dmy;
cin >> parse("%d %m %Y", dmy);
cout << format("%A", weekday{dmy}) << '\n';
}
Upvotes: 8
Reputation: 51
I had the same problem, and I was able to find a simple solution.
According to this post:
"Following is a simple function suggested by Sakamoto, Lachman, Keith and Craver to calculate day. The following function returns 0 for Sunday, 1 for Monday, etc."
int dayofweek(int d, int m, int y)
{
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return ( y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
}
Upvotes: 3
Reputation: 4884
You can use the Gregorian Date System from the Boost C++ library to find the day of week of a given date. Here is a simple example:
#include <boost/date_time.hpp>
#include <string>
#include <iostream>
const static std::string daysOfWeek[] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
int getDayOfWeekIndex(int day, int month, int year) {
boost::gregorian::date d(year, month, day);
return d.day_of_week();
}
int main()
{
const int index = getDayOfWeekIndex(30, 07, 2018);
std::cout << daysOfWeek[index] << '\n';
}
This code prints Monday
.
Upvotes: 6
Reputation: 29
int dayofweek(int day,int month,int year)
{
int arr[] = {0,3,2,5,3,5,1,4,6,2,4};
if(month<3)
year--;
return ((year+year/4-year/100+year/400+arr[month-1]+day)%7);
}
int main()
{
int day,month,year;
cout<<"Enter the Date for which day of the week need to be find (DD/MM/YYYY)."<<endl;
cin>>day>>month>>year;
int x = dayofweek(day,month,year);
if(x==0)
cout<<"Sunday"<<endl;
else if(x==1)
cout<<"Monday"<<endl;
else if(x==2)
cout<<"Tuesday"<<endl;
else if(x==3)
cout<<"Wednesday"<<endl;
else if(x==4)
cout<<"Thursday"<<endl;
else if(x==5)
cout<<"Friday"<<endl;
else if(x==6)
cout<<"Saturday"<<endl;
}
Upvotes: -2
Reputation: 814
What happens when a number is perfectly divisible by 7?
14 / 7 = 2 14 % 7 = 0
The modulo operator (% n) will return a number from 0 to n -1
if n is divided by 7 the remainder can never be 7 so
int b = (a - 2) % 7;
switch (b){
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
case 7:
return "Sunday";
}
}
In this case it can never be Sunday
Try this
int b = (a - 2) % 7;
switch (b){
case 0:
return "Sunday";
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
default:
return "Error";
}
Upvotes: 1
Reputation: 3758
First: Do not write your own function, if there already are standardized functions that can handle the same problem. Point is that you might easily make a mistake (and I can already see one in the first line of your weekday()
function as it is now), whereas implementations of standardized functions have been tested thoroughly and you can be confident that they deliver the result you are expected to get.
That being said, here is a possible approach using std::localtime and std::mktime:
#include <ctime>
#include <iostream>
int main()
{
std::tm time_in = { 0, 0, 0, // second, minute, hour
9, 10, 2016 - 1900 }; // 1-based day, 0-based month, year since 1900
std::time_t time_temp = std::mktime(&time_in);
//Note: Return value of localtime is not threadsafe, because it might be
// (and will be) reused in subsequent calls to std::localtime!
const std::tm * time_out = std::localtime(&time_temp);
//Sunday == 0, Monday == 1, and so on ...
std::cout << "Today is this day of the week: " << time_out->tm_wday << "\n";
std::cout << "(Sunday is 0, Monday is 1, and so on...)\n";
return 0;
}
Upvotes: 24