/*
Name:
Student Number:
Date the code was written:
Description: This program implements a set of functions which perform various operations on calendar dates.
*/
#include <stdio.h>
/* is_leap_year(year)
Given a year, determine whether that year is a leap year.
Parameters: year (integer)
Return value (integer):
- If the year is a leap year, return 1
- Otherwise, return 0
For this function _only_, you may assume that the year number
will always be valid (that is, greater than or equal to 1).
*/
int is_leap_year(int year){
if(year%4 != 0){
return 0;
}
if(year%100 != 0){
return 1;
}
if(year%400 != 0){
return 0;
}
return 1;
}
/* days_in_year(year)
Given a year, return the number of days in that year.
A leap year has 366 days. All other years have 365 days.
Parameters: year (integer)
Return value (integer):
- If year is valid (greater than or equal to 1),
return the number of days in that year.
- If year is invalid (negative or zero), return -1.
*/
int days_in_year(int year){
if(year <= 0){
return -1;
}
if(is_leap_year(year) == 1){
return 366;
}
return 365;
}
/* days_in_month(year, month_number)
Given a year and a numerical representation of the month (where 1 is January
and 12 is December), return the number of days in that month.
Note that the number of days in February (month 2) will vary depending on
whether the year is a leap year.
Parameters: year (integer), month_number (integer)
Return value (integer):
- If the month number is valid (between 1 and 12, inclusive),
the return value will be the number of days in the provided
month during the provided year.
- If the month number is invalid (negative, zero, greater than 12),
or the year number is invalid (negative or zero),
the return value will be -1.
*/
int days_in_month(int year, int month_number){
if(year <= 0){
return -1;
}
if(month_number < 1 || month_number > 12){
return -1;
}
if(month_number == 1 || month_number == 3 || month_number == 5 || month_number == 7 || month_number == 8 || month_number == 10 || month_number == 12){
return 31;
}
if(month_number == 4 || month_number == 6 || month_number == 9 || month_number == 11){
return 30;
}
//if(month_number == 2){
if(is_leap_year(year)) {
return 29;
}
return 28;
//}
}
/* date_valid(year, month_number, day)
Determine if a particular year/month/day combination is a valid date.
For example, the dates 2018-01-31, 2020-02-29 and 2022-09-15 are valid,
but the dates 2022-01-32, 2019-02-29 and 2022-15-09 are not.
Specifically, a date is valid if
- The year number is greater than or equal to 1
- The month number is between 1 and 12 (inclusive)
- The day number is between 1 and the number of days in the provided
month during the provided year (note that the number of days in each
month may vary depending on whether the year is a leap year).
Parameters: year (integer), month_number (integer), day (integer)
Return value (integer):
- If the date is valid, return 1
- Otherwise, return 0
*/
int date_valid(int year, int month_number, int day){
if(year <= 0){
return 0;
}
if(month_number < 1 || month_number > 12){
return 0;
}
if(day < 1 || day > days_in_month(year, month_number)){
return 0;
}
return 1;
}
/* day_index(year, month_number, day)
Given a date, return the day index of that date within its year.
The day index is the number of days between the beginning of the year
and the date. For example, the day index of 2024-01-01 is 1 and the day
index of 2024-12-31 is 366 (since 2024 is a leap year).
Parameters: year (integer), month_number (integer), day (integer)
Return value (integer):
- If the date is valid, return the day index of the date
- Otherwise, return -1
*/
int day_index(int year, int month_number, int day){
int i;
int index = 0;
if(date_valid(year, month_number, day) == 0){
return -1;
}
for(i = 1; i < month_number; i++){
index += days_in_month(year, i);
}
index += day;
return index;
}
/* chronological_order(year1, month1, day1, year2, month2, day2)
Given two dates year1/month1/day1 and year2/month2/day2, determine which
date is chronologically earlier (or whether the two dates are equal).
Parameters (all integers): year1, month1, day1, year2, month2, day2
Return value (integer):
- If either (or both) of the provided dates is invalid, return -1.
- If the two dates are both valid and year1/month1/day1 is chronologically
earlier than year2/month2/day2, return 1.
- If the two dates are both valid and year1/month1/day1 is chronologically
later than year2/month2/day2, return 2.
- If the two dates are both valid and exactly equal, return 0.
*/
int chronological_order(int year1, int month1, int day1, int year2, int month2, int day2){
if(date_valid(year1, month1, day1) == 0 || date_valid(year2, month2, day2) == 0){
return -1;
}
if(year1 < year2){
return 1;
}
if(year1 > year2){
return 2;
}
if(month1 < month2){
return 1;
}
if(month2 < month1){
return 2;
}
if(day_index(year1, month1, day1) < day_index(year2, month2, day2)){
return 1;
}
if(day_index(year2, month2, day2) < day_index(year1, month1, day1)){
return 2;
}
return 0;
}
/* days_in_range(start_year, start_month, start_day, end_year, end_month, end_day)
Given two dates (year, month, day), determine the total number of days in the range
defined by those two dates, including the dates themselves.
For example, the number of days between 2022-01-05 and 2022-01-10
is six (2022-01-05,2022-01-06,2022-01-07,2022-01-08,2022-01-09,2022-01-10).
Parameters (all integers): start_year, start_month, start_day, end_year, end_month, end_day
Return value (integer):
- If either or both of the start date or end date is not a valid date
(as determined by the date_valid function above), return -1.
- If the start date is chronologically later than the end date, return -1.
- If the start date and end date are both valid dates, and the start date is chronologically
earlier than or equal to the end date, return the number of days in the range.
*/
int days_in_range(int start_year, int start_month, int start_day, int end_year, int end_month, int end_day){
if(date_valid(start_year, start_month, start_day) == 0 || date_valid(end_year, end_month, end_day) == 0){
return -1;
}
if(chronological_order(start_year, start_month, start_day, end_year, end_month, end_day) == 2){
return -1;
}
if(chronological_order(start_year, start_month, start_day, end_year, end_month, end_day) == 0){
return 1;
}
if(start_year == end_year){
return (day_index(end_year, end_month, end_day) - day_index(start_year, start_month, start_day) + 1);
}
int total = 0;
total += (days_in_year(start_year) - day_index(start_year, start_month, start_day) + 1);
int i;
for(i = start_year+1; i < end_year; i++){
total += days_in_year(i);
}
total += day_index(end_year, end_month, end_day);
return total;
}
int main(){
/* The code in main() will not be marked (we will replace your main() with
our own code for testing). The code below does some basic testing of the
functions above, but we will use different test cases for marking,
so you should add extra tests to verify your code.
Remember to test unusual or "edge" cases as well as normal inputs.
For example, make sure to test the behavior of each function
on invalid dates (not just valid ones).
*/
int result;
/* Test is_leap_year */
result = is_leap_year(2022); //Should be 0
printf("is_leap_year(2022): %d\n", result );
result = is_leap_year(2020); //Should be 1
printf("is_leap_year(2020): %d\n", result );
result = is_leap_year(1600); //Should be 1
printf("is_leap_year(1600): %d\n", result );
result = is_leap_year(1700); //Should be 0
printf("is_leap_year(1700): %d\n", result );
result = is_leap_year(1870); //Should be 0
printf("is_leap_year(1870): %d\n", result );
/* Test days_in_year */
result = days_in_year(2022); //Should be 365
printf("days_in_year(2022): %d\n", result );
result = days_in_year(2020); //Should be 366
printf("days_in_year(2020): %d\n", result );
result = days_in_year(1600); //Should be 366
printf("days_in_year(1600): %d\n", result );
result = days_in_year(1700); //Should be 365
printf("days_in_year(1700): %d\n", result );
result = days_in_year(1870); //Should be 365
printf("days_in_year(1870): %d\n", result );
/* Test days_in_month */
result = days_in_month(2022, 1); //Should be 31
printf("days_in_month(2022, 1): %d\n", result );
result = days_in_month(2022, 2); //Should be 28
printf("days_in_month(2022, 2): %d\n", result );
result = days_in_month(2022, 4); //Should be 30
printf("days_in_month(2022, 4): %d\n", result );
result = days_in_month(2020, 2); //Should be 29
printf("days_in_month(2020, 2): %d\n", result );
result = days_in_month(1999, 3); //Should be 31
printf("days_in_month(1999, 3): %d\n", result );
result = days_in_month(2006, 2); //Should be 28
printf("days_in_month(2006, 2): %d\n", result );
result = days_in_month(0, 2); //Should be -1
printf("days_in_month(0, 2): %d\n", result );
result = days_in_month(-20, 2); //Should be -1
printf("days_in_month(-20, 2): %d\n", result );
result = days_in_month(-20, -5); //Should be -1
printf("days_in_month(-20, -5): %d\n", result );
result = days_in_month(-20, 20); //Should be -1
printf("days_in_month(-20, 20): %d\n", result );
result = days_in_month(-20, 0); //Should be -1
printf("days_in_month(-20, 0): %d\n", result );
/* Test date_valid */
result = date_valid(2022, 1, 11); //Should be 1
printf("date_valid(2022, 1, 11): %d\n", result );
result = date_valid(2022, 2, 29); //Should be 0
printf("date_valid(2022, 2, 29): %d\n", result );
result = date_valid(2020, 2, 29); //Should be 1
printf("date_valid(2020, 2, 29): %d\n", result );
result = date_valid(2022, 1, 87); //Should be 0
printf("date_valid(2022, 1, 87): %d\n", result );
result = date_valid(2022, 6, 31); //Should be 0
printf("date_valid(2022, 6, 31): %d\n", result );
result = date_valid(-20, 6, 31); //Should be 0
printf("date_valid(-20, 6, 31): %d\n", result );
result = date_valid(20, 13, 31); //Should be 0
printf("date_valid(20, 13, 31): %d\n", result );
/* Test day_index */
result = day_index(2022, 6, 10); //Should be 161
printf("day_index(2022, 6, 10): %d\n", result );
result = day_index(2022, 10, 6); //Should be 279
printf("day_index(2022, 10, 6): %d\n", result );
result = day_index(2016, 6, 10); //Should be 162
printf("day_index(2016, 6, 10): %d\n", result );
result = day_index(2012, 10, 6); //Should be 280
printf("day_index(2012, 10, 6): %d\n", result );
result = day_index(2012, 13, 13); //Should be -1
printf("day_index(2012, 10, 6): %d\n", result );
/* Test chronological_order */
result = chronological_order(2021, 10, 6, 2022, 6, 10); //Should be 1
printf("chronological_order(2021, 10, 6, 2022, 6, 10): %d\n", result );
result = chronological_order(2022, 10, 6, 2022, 6, 10); //Should be 2
printf("chronological_order(2022, 10, 6, 2022, 6, 10): %d\n", result );
result = chronological_order(2022, 6, 10, 2022, 6, 10); //Should be 0
printf("chronological_order(2022, 6, 10, 2022, 6, 10): %d\n", result );
result = chronological_order(2021, 6, 10, 2021, 6, 31); //Should be -1
printf("chronological_order(2021, 6, 10, 2021, 6, 31): %d\n", result );
result = chronological_order(2021, 0, 10, 2021, 6, 31); //Should be -1
printf("chronological_order(2021, 0, 10, 2021, 6, 31): %d\n", result );
/* Test days_in_range */
result = days_in_range(2021, 12, 20, 2022, 1, 11); //Should be 23
printf("days_in_range(2021, 12, 20, 2022, 1, 11): %d\n", result );
result = days_in_range(2019, 10, 6, 2020, 6, 10); //Should be 249
printf("days_in_range(2019, 10, 6, 2020, 6, 10): %d\n", result );
result = days_in_range(2019, 10, 6, 2019, 10, 6); //Should be 1
printf("days_in_range(2019, 10, 6,2019, 10, 6): %d\n", result );
result = days_in_range(2022, 10, 6, 2019, 10, 6); //Should be -1
printf("days_in_range(2022, 10, 6, 2019, 10, 6): %d\n", result );
result = days_in_range(2019, 11, 6, 2019, 10, 6); //Should be -1
printf("days_in_range(2019, 11, 6, 2019, 10, 6): %d\n", result );
result = days_in_range(2019, 10, 7, 2019, 10, 6); //Should be -1
printf("days_in_range(2019, 10, 7, 2019, 10, 6): %d\n", result );
return 0;
}
1 Overview
This assignment covers control flow, including if-statements and functions, as well as the use of
various arithmetic operators. It also provides an introduction to error handling in cases where a
program component receives incorrect data, and to unit testing to validate the correctness of a
set of functions.
You will implement a set of functions which perform various operations on calendar dates. A
template file date_functions.c has been provided containing several empty functions (along with
a main () function containing some simple tests). Your task is to implement each function according
to the specification given in the comments above the function. You may also add extra functions as
needed, but you are not permitted to change the function signature of the existing functions in any
way. For example, you may not rename the functions, change the types or names of the parameters,
add new parameters or modify the return type. Submissions which violate this requirement will
receive a mark of zero.
Although each function will be marked separately, you must ensure that the entire file compiles
successfully (since a syntax error in one function will make it impossible for the teaching team to
compile your submission and mark any of your functions).
You are responsible for thoroughly testing each function. Some basic tests have been provided in
the main() function of the template, but you will need to do more testing to fully validate your
implementations. When the code is tested, we will substitute our own main() function to test your
code. Note that the contents of main() in your submission will not be marked (although, as
mentioned above, you must ensure that the entire file compiles successfully, including whatever
code you put in main()); all of the marks for this assignment are based on the other functions.
The sections below describe each function in more detail. In the event that this document is not
consistent with the specifications written in the posted template code, the template code will be