Correct expression for checking leap years [duplicate] - calendar

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to find leap year?
What will be the exact definition of leap year? AFAIK "A year which is divisible by 4 is a leap year. But for century years' the years which are divisible by 400 is a leap year."
But that definition makes 100, 200, 300, 400.... upto 1700 NOT LEAP years! But in Gregorian calendar all of them are all leap year, check this out.
You can also try "call 1700" in Linux to verify.
So the correct algorithm for leap years would be:
if ( (year % 4 == 0) && ( year <= 1700 || year % 100 != 0 || year % 400 == 0 ))
printf("%d is a leap year.\n", year);
else
printf("%d is not a leap year.\n", year);
But is this specific to Gregorian calendar? Even if that is the case why is it not mentioned here?
Regards,
PS:The history of Gregorian callender seems interesting check out the September month of 1752.

I think it's important to separate the idea of historical dates on the one hand and date calculation on the other. Historical dates are subject to all kinds of political, social, and technological issues, and are thus not very suitable for a simple algorithm. See this page for the wide disparity in the adoption of the modern Gregorian calendar.
The usual practice when calculating dates is to forget about history and just pretend that the existing system has always been in place and will always be in place. (Unless you are an astronomer or certain other kinds of scientist, in which case you would use something even more accurate, and would be even less interested in historical dates.) If your application is all about recorded historical dates, then you are going to need a way to map those dates (which depend on the country, the period in history, etc.) to a more calculation-friendly universal dating system anyway.

For one thing, your algorithm is a bit off. It's more like:
if ( (year % 4 == 0) && ( year % 100 != 0 || year % 400 == 0 ))
printf("%d is a leap year.\n", year);
else
printf("%d is not a leap year.\n", year);
Also, the Gregorian calendar was not adopted until 1582 or so.
Edit:
The Gregorian calendar was decreed in 1582, but adopted by various countries at various times, as late as 1926 in Turkey.

"But is this specific to Gregorian calendar"
Yes.
Please read this http://en.wikipedia.org/wiki/Leap_year
Because of the orbits of Earth (and Moon), we have a variety of calendars, each with complex rules for trying to get a rational match between days and years.
Please read this http://en.wikipedia.org/wiki/Gregorian_calendar
Please buy a copy of http://emr.cs.uiuc.edu/home/reingold/calendar-book/index.shtml

Read down the web page you linked to. The reason for the gap in September 1752 is that is when the UK converted from Julian to Gregorian calendars, it is not a gap in Gregorian calendar but the difference between the two.
The page you link to uses the Julian calendar up until that point. Therefore the algorithm you use for calculating leap years is different to the way the page (or the UK, or England, though neither existed in AD 100) calculated for years before 1752.

Have a look here. I'll copy some of the pseudo-code here for reference:
if (year modulo 4 is 0) and ((year modulo 100 is not 0) or (year modulo 400 is 0))
then is_leap_year
else
not_leap_year

If your platform has a Date datatype, your first try would be to use whatever date expression and manipulation features it has. Usually these are sufficient, and you can save yourself the trouble of taking responsibility for supporting YA date-handling library.
So the answer to your question would be the equivalent of:
if(exists("02/29/yyyy".toDate)) ...

Related

Calculate Age of user WITH Datediff (?)

i'm trying to use the Datediff function to give me the years off a user but this is more complicated than i thought.
SELECT DATEDIFF( DD,'1963-07-22','2016-07-23')
This will give me 19360 Days i think that is because 2016 have a Leap Year and that is fine.
what i would like to do is get the YEAR and not the days.
if i change the interval from DD to YY(YYYY) it only calculates the year.
In my experience it does work best to use the number of days between the two dates and then divide that amount by 365.25 to be exact, then round off to even years. This would give you the most precise age in years I think.
The correct answer to calculate someone's age, or the difference in truncated years between two dates is
year(#today)-year(#birthDate)+floor((month(#today)-month(#birthdate)+floor((day(#today)-day(#birthdate))/31))/12);
This will work regardless of leap years. And correct for whether the person was born on a later month or even a later day in the same month. This will also ignore hours and minutes, as should be when calculating someone's age.
When using "yyyy" in DateDiff only the year parts of the dates are used to calculate the difference. The month and day are omitted. This will produce results that are sometimes correct and sometimes incorrect by one year.
Try using this instead.
SELECT Int((#2016-07-23#-#1963-07-22#)/365.25);

Add years, months and days to date C

I am trying to write an algorithm that takes an input of a date ("2000-01-01") and also "y|m|d", where y is the number of years to add to the original date and m and d are the months and days. This algorithm needs to take into account leap years as well. Sorry I haven't posted any code, I haven't really got anything working yet.
The algorithm also needs to work like this: if you add three months to 30th November, you would get 28th February the next year, or 29th if it is a leap year. So if the month you are coming from as a length higher than the final resultant month, the last day of the final resultant month will be taken.
Could someone please give me some pointers on how to write it or link to any useful resources?
I hope that this makes sense, any questions let me know. Thanks.
You seem to have the problem quite well figured out. Here is the algorithm for finding a leap year:
if year is not divisible by 4 then common year
else if year is not divisible by 100 then leap year
else if year is not divisible by 400 then common year
else leap year
Most, if not all of what you need can be found in the <ctime> library (http://www.cplusplus.com/reference/ctime/).
In particular look up the time_t and struct tm types and how to convert between the two (localtime(), gmttime(), ...). Note that you can add days, hours, months, etc to the fields in a struct tm and they are handled properly, e.g., the "32nd of January" becomes "Feb. 1st".
The <ctime> library also handles leap years.
Your way of adding 3 months seems non conventinal, so you might have to check this by hand. Still easy enough by using <ctime>.
EDIT: Before somebody complains that <ctime> is c++, in plain c this library is in <time.h>.

Calculating dates ( with limited tools)

I'm trying go calculate difference between two dates, for homework.
Only problem is we can't use anything outside of for while if loops.. which is driving me crazy. I tried writing the sudocode for it and it seems simple enough but when I start sitting down and coding I get lost when the months start coming in.(excluding leap years)
Say the start dates is July 3 2015 going to March 5 2016.
I was originaly going to add days until the current month is finish and pretty much calculate everything from days. But I get kinda lost when I start including different days for each month.
An idea to work out how far you can go in that month might be
for(day=1;day<=days_in_month(month);day++){
counter++;
}
Then have a days_in_month function, that returns, using a few if statements. If you have a bit of google I remember seeing a few good statements to efficiently work this out - if you need to include leap years you'll obviously need to pass the year to the days_in_month function.
Oviously you'll need the above loop nested some other ones.
Hope this helps, good luck.
Step 1: Write a function to convert a date into a "day number since epoc", which takes into account things like leap years, etc. The epoc could probably be "1/1/1970". It'd be easy to just use lookup tables - one for "days in previous years" that includes a leap year flag and one for "days in previous months" for non-leap years (where if the leap year flag from the previous table is set and the month is after February, you add a day). Then you'd add "days in previous years", "days in previous months" and the day of the month to get "day number since epoc".
Step 2: Convert both dates into "day number since epoc" integers and subtract.
Note: The lecturer might expect you to use calculations rather than using lookup tables. In this case, use lookup tables to get it working, then replace the lookup tables one at a time.

Input year, then print calendar

I am stuck on the following problem from my C programming class:
Write a program that prompts the user to input a year, and then outputs the calendar(for the entire year).
I have no idea how to approach this problem. I can usually start my homework problems (this is an optional challenge problem), but I am really lost. We've worked through chapters 1-10 of Deitel & Deitel (loops, arrays, pointers, I/O, etc), but I don't know how to approach this at all. Any hints or suggestions would be appreciated.
It might help you to understand the mathematics of the calendar. If the fabulous book Calendrical Calculations is not in your university library, they may be able to get you a reprint of the article by the same authors in Software—Practice & Experience. And ask your prof to request the book for the library.
In general, when you have a big problem like this one, you want to break it down into little problems that are easier to solve.
Here's one possible little problem to start with: if you know how many days there are in a month, and what weekday the first of the month falls on, could you output a calendar for that month?
The hardest part is determining which day of the week the year starts on.
http://en.wikipedia.org/wiki/Calculating_the_day_of_the_week
But even without that knowledge, when I first implemented this, I used a reference date (for example, you know that today, January 11, 2010 is a Monday) and counted days from there. (Just keep in mind that leap years have an extra day, and that leap years are every 4 years except every 100 years except every 400 years.)
http://en.wikipedia.org/wiki/Leap_year
Does this code qualify? :-)
char command[]="cal 2010";
sprintf(command,"cal %d",argv[1]);
system(command);
It assumes a Unix machine with cal in the path.
you need to find out first the day on 1st of january
and then print the dates.
GO to https://sourceforge.net/projects/c-cpp-calender/
go through the code and you will understand it
A good start may be the localtime(3) and mktime(3) functions. Alternatively, you can implement the relevant date arithmetic from scratch. Then, simply, generate the first line of the calendar (find the weekday that corresponds to January 1st, then print taht in the right place, followed by the rest of the week), then print all but the last lines, then print the last line.
Depending on if you want a calendar paginated by month or not, this MAY be better done ona per-month instead of a per-year basis.
Well, first figure out the algorithmic part of your problem - given a year, find what day Jan 1st is.
After this, just note the number of days in each month (store it in an array, say num_days[]), and the note the number of months in a year and an array of strings for the months.
For e.g. the outermost loop iterates over the months. Say, iterate for(i=0;i<NumMonths;++i). Then, for each month, print the string, e.g. month[i], then a newline.
Then, with simple tabs, print Sun Mon Tue ..., and another newline.
Then using the day Jan 1st corresponds to (call it FirstDay), insert spaces, and start with that day. Keep printing the dates and newlines till you hit max_month[i] which is 31 (for January). Store the name of day of the last day of the previous month and just reiterate treating that day as FirstDay.
You need a couple pieces to start. First, you need a formula that computes the day of the week for January 1 of whatever year is entered. You'll also need a formula to determine if the year is a leap year. Both of these formulae are easily found with a simple Google search. The third item you need is a simple array containing the number of days in each of the 12 months for a non-leap year.
Once you have these things, its trivial to determine the week day for each month of the year. Make sure to account for February 29 in a leap year. From there, you just need to create a function that primts out the monthly calendar in a form that looks similar to the calendar hanging on the wall. Try sketching out the desired layout on paper first and use that as a template for creating the appropriate format statements.
Might check out the doomsday algorithm. This would get you certain "dooms days" like Jan 31 is a doomsday, for 2008, that was a saturday. You can work backwords from there
Basically, there are two approaches:
The easy / pragmatical way: Solve the task, and forget about everything else. Here you may check documentation for mktime() (you'll find an example based on mktime below..).
The scientific / engineering way: Learn to know how it works! You can start at the great wikipedia article about the gregorian calendar. Read it, understand it, and write code that implements the underlying algorithms (which are known, no rocket science, it is possible). This will improve your skills a lot (in fact, you really should do such a thing, maybe not the calender but another topic, it will give you a big leap in understanding all things).
Now some pragmatic code to start with. mktime() has a great feature: it knows the calender details, and it accepts e.g. a date "2010-01-60" and will convert it into February 29th, 2010. But, this will only work for dates after 1970. It will not work for earlier dates (though I am not 100% sure, but it shouldn't work, because unix time starts at January 1st, 1970, but try with other dates, maybe mktime() is not restricted to unix time).
Pseudo-Code, this prints each day on a single line (YYYY-MM-DD):
void print_cal( int year ) {
static char weekdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
struct tm tm;
for( int day=0; day<365; ++day ) {
memset( &tm, 0, sizeof(tm) );
tm.tm_year = year - 1900;
tm.tm_mday = day;
mktime( &tm ); // modifies tm
printf( "%04d-%02d-%02d, %s\n", tm.tm_year, tm.tm_mon+1, tm.tm_mday, weekdays[tm.tm_wday] );
}
}
This code ignores leap years. You still have to adjust it to be correct for leap years! Also the result is not very pretty yet, just one line per day.
EDIT: added output of weekdays.

Calculate time period using C

How do I calculate the time period between 2 dates in C (any library, etc.)?
The program should take two (local) dates as input and provide the duration period between them as output.
For example,
startDate = OCT-09-1976 and endDate = OCT-09-2008
should show a duration of 32 years.
startDate = OCT-09-1976 and endDate = DEC-09-2008
should show a duration of 32 years and 2 months.
Thanks.
Convert the dates into two struct tm structures with strptime
Difftime gives you the difference between the two in seconds.
Convert that into months etc with the code here (in C++, but the only C++ is for the string formatting, easy to change)
EDIT: as a commentor observed, that avoids the month issue. There is (GPL'd) code for
isodiff_from_secs that can be converted to do what you want, if you're happy with its assumption that months have 30 days. See Google codesearch and the description of the standard here
Doing the fully-correct solution which takes acccount of the true months between the actual days would be pretty complex. Is that required for your problem?
I did something very similar recently using Boost.Date_Time, and presenting the resulting function as C, but this of course requires using the C++ linker.
Actually, the example leaves a little to be desired - will the start and end dates always be on the same day of the month? If so you can ignore the day number end up with a trivial subtraction of the month and year numbers.
However if your dates can be anywhere in the month it might be a bit more tricky. Remember that not all months have the same number of days!
C difftime doesn't help you with month calculations, which is why I used Boost, though you may not have that option.

Resources