Skip to content

Instantly share code, notes, and snippets.

@abiiranathan
Last active May 6, 2022 10:28
Show Gist options
  • Save abiiranathan/6a6dc7e44fd747e515a1b5666b1c6552 to your computer and use it in GitHub Desktop.
Save abiiranathan/6a6dc7e44fd747e515a1b5666b1c6552 to your computer and use it in GitHub Desktop.
A C program to calculate age from birth date.
// prints age given date of birth in form dd/mm/yyyy
// compile with: gcc age.c -o age
// Author: Dr. Abiira Nathan
// Date: May, 2022
// Version: 1.0
// License: MIT License
// Copyright (c) 2020 Dr. Abiira Nathan
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct
{
int date, month, year;
} date;
// returns the number of digits in an integer n
int num_digits(int n)
{
int count = 0;
while (n > 0)
{
n /= 10;
count++;
}
return count;
}
// Check if year is leap year
bool is_leap(int year)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
return true;
else
return false;
}
/*
Returns the age in a human readable format.
If age is greater than or equal to 1 year, it will return the age in years +/- months(if years < 2)
If the age is less than 1 year, it will return the age in months +/- days(months < 2).
If the age is less than 1 month, it will return the age in days.
*/
char *humanize(int years, int months, int days)
{
// return date of birth as a string
// e.g "22 years" or "4 years, 3 months" or "5 days"
char *str = (char *)malloc(sizeof(char) * 11);
// years or years and months
if (years > 0)
{
sprintf(str, "%d year%s", years, (years > 1) ? "s" : "");
if (months > 0 && years < 2)
sprintf(str, "%s, %d month%s", str, months, (months > 1) ? "s" : "");
return str;
}
// months or months and days
if (months > 0)
{
sprintf(str, "%d month%s", months, (months > 1) ? "s" : "");
if (days > 0 && months < 2)
sprintf(str, "%s, %d day%s", str, days, (days > 1) ? "s" : "");
return str;
}
// days
sprintf(str, "%d day%s", days, (days > 1) ? "s" : "");
return str;
}
// calculates age given date of birth in days, months, years
// returns the date struct with the age in years, months, days
date findAge(int birth_date, int birth_month, int birth_year)
{
struct tm *now_t;
time_t current = time(NULL);
now_t = localtime(&current);
int current_date, current_month, current_year;
current_date = now_t->tm_mday;
current_month = now_t->tm_mon + 1;
current_year = now_t->tm_year + 1900;
// days of every month
int month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// if leap year
if (is_leap(current_year))
{
month[1] = 29;
}
// if birth date is greater then current birth
// month then do not count this month and add 30
// to the date so as to subtract the date and
// get the remaining days
if (birth_date > current_date)
{
current_date = current_date + month[birth_month - 1];
current_month = current_month - 1;
}
// if birth month exceeds current month, then do
// not count this year and add 12 to the month so
// that we can subtract and find out the difference
if (birth_month > current_month)
{
current_year = current_year - 1;
current_month = current_month + 12;
}
// calculate date, month, year
date d;
d.year = current_year - birth_year;
d.month = current_month - birth_month;
d.date = current_date - birth_date;
return d;
}
int main(void)
{
date dob;
struct tm bd_t;
printf("Enter the date of birth(dd/mm/yyyy): ");
int res = scanf("%d/%d/%d", &dob.date, &dob.month, &dob.year);
if (res != 3 || dob.date < 1 || dob.date > 31 ||
dob.month < 1 || dob.month > 12 || dob.year < 1 || num_digits(dob.year) != 4)
{
printf("Invalid birth date: %.2d/%.2d/%4d\n", dob.date, dob.month, dob.year);
return EXIT_FAILURE;
}
date age = findAge(dob.date, dob.month, dob.year);
char *age_str = humanize(age.year, age.month, age.date);
printf("Age: %s\n", age_str);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment