Simon Soka
Simon Soka

Reputation: 79

c++ get years between date chosen by user and actual date(counting days,months,years)

i tried doing this:

struct Den_t
{
    int day, month, year;
}; 

int main()
{
        struct Den_t* Datum = new struct Den_t;
        struct Den_t* Dnes = new struct Den_t;

    time_t theTime = time(NULL);
    struct tm aTime;
    localtime_s(&aTime, &theTime);

    Dnes->day = aTime.tm_mday;
    Dnes->month = aTime.tm_mon + 1;
    Dnes->year = aTime.tm_yday + 1900;

    cin >> Datum->day >> Datum->month >> Datum->year;
    if (Dnes->year - Datum->year >= 18 )
        cout << "full aged " << endl;
    else
        cout << "not full aged " << endl;
    system("PAUSE");
    return 0;
}

but i somehow cant understand what should i even compare and decrement,could someone explain me

what else i need to do to tell people's date for example in float by comparing year,month and day of actual time and date user inputs in the program?

Upvotes: 1

Views: 1713

Answers (2)

Howard Hinnant
Howard Hinnant

Reputation: 218710

Using these libraries:

http://howardhinnant.github.io/date/date.html

http://howardhinnant.github.io/date/tz.html

This is how I would tackle the problem. First the code, then the explanation:

#include "tz.h"
#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono;
    std::cout << "Enter birthday [day month year]:";
    int di, mi, yi;
    std::cin >> di >> mi >> yi;
    if (std::cin.fail())
    {
        std::cout << "Invalid date\n";
        return 1;
    }
    auto y = year{yi};
    if (!y.ok())
    {
        std::cout << "Invalid year\n";
        return 1;
    }
    auto m = month(mi);
    if (!m.ok())
    {
        std::cout << "Invalid month\n";
        return 1;
    }
    auto d = day(di);
    if (!d.ok())
    {
        std::cout << "Invalid day\n";
        return 1;
    }
    auto birthday = y/m/d;
    if (!birthday.ok())
    {
        std::cout << "Invalid birthday\n";
        return 1;
    }
    auto local_time = current_zone()->to_local(system_clock::now());
    auto today = year_month_day{floor<days>(local_time)};
    auto age = today.year() - birthday.year();
    if (birthday + age > today)
        --age;
    if (age >= years{18})
        std::cout << "full aged at " << age.count() << "\n";
    else
        std::cout << "not full aged at " << age.count() << "\n";
}

I would first go to some trouble to check the validity of the user input. What I have below seems like a minimum:

  • It must be integral input.
  • Each integral input must have a reasonable value (e.g. month must be in the range [1, 12].
  • The combination y/m/d must be a valid date.

A more robust program might give the user some feedback on what he input, and give him another chance to correct his mistake.

Once assured we have a valid birthday, we need to get the current date in the local timezone. This:

auto local_time = current_zone()->to_local(system_clock::now());

gets the local time.

This local time can be converted to a local year, month and day with:

auto today = year_month_day{floor<days>(local_time)};

This computation follows the custom that your birthday begins at the local midnight, regardless of what time of day (and where on the planet) you were actually born. In other words, once the local year/month/day is established, this problem is independent of the local time zone, and even the local time of day.

Next, the current age is computed:

auto age = today.year() - birthday.year();
if (birthday + age > today)
    --age;

The difference between the years of today and the birthday is a first approximation to the age. This approximation is refined by computing the date on which your birthday falls this year. If this year's birthday is still in the future, then by custom we count that as one year younger. If we were doing something that leaned less towards a legal system, and more towards scientific work, we might well compute in other ways, such as rounding to the nearest year (also easy to do with this library).

If the birthday is on Feb 29, the above code still works: birthday + age will result (75% chance) in an invalid date, e.g.: feb/29/2015. However this invalid date will correctly compare greater than feb/28/2015 and less than mar/1/2015, exactly as we need it to! Invalid dates are your friend, not your enemy -- you just have to know they exist and what to do about them.

Now it is a simple matter to report your findings:

if (age >= years{18})
    std::cout << "full aged at " << age.count() << "\n";
else
    std::cout << "not full aged at " << age.count() << "\n";

Upvotes: 0

Roman Pustylnikov
Roman Pustylnikov

Reputation: 1932

You have an issue with your code logic here. For example:

Datum is 31/12/1982
Dnes is 01/01/2000

The year difference is 18 but the age is 17 and 2 days.

Consider using standard library functions instead of reinventing the wheel. difftime could be useful, for example

This is a very dirty example, but it would do the work:

   time_t dnes;
   time(&dnes);

   // Set datum here ... 
   cin >> Datum->day >> Datum->month >> Datum->year;
   datum.tm_mday = Datum->day;
   datum.tm_mon =  Datum->month - 1;
   datum.tm_yday = Datum->year - 1900;

   datum->tm_yday+=18;

   if (difftime(dnes, mktime(&datum)) <0 )
        cout << "not full aged " << endl;
    else
        cout << "full aged " << endl;

Upvotes: 1

Related Questions