Dat To
Dat To

Reputation: 45

How to deal with time in C++

I have a question about managing the date and time in c++. I have two classes Plane and Flight in my program.

My Plane will consist data as:

string tailNumber;//Plane's unique trait
vector<vector<string>> planeSchedule;//2D string vector to contain plane's depature date and arrival date

My Flight class will consist data as:

string tailNumber;//Plane's unique trait
string departureDate;
string arrivalDate;

In my main class, I will input the value for departureDate and arrivalDate in format: "YYYY/MM/DD HH:MM" such as: "2019/04/15 10:30" and "2019/04/16 9:30" (I will use the 24-hour format and time will be GMT).

My question is how do I convert the two strings above to a proper format to store in my planeSchedule, so that I will be able to avoid the time conflict in the planeSchedule.

For example, If the next time I'm adding a flight with departure and arrival date beetween the: 2019/04/15 10:30" and "2019/04/16 9:30" such as: "2019/04/15 13:30" and "2019/04/16 7:30", I will get an error like "Flight conflict, plane is not available to flight."

My professor recommends using an unsigned long int to store time, but I really do not know where to start to solve this problem. Any help/suggestion is appreciated.

Upvotes: 0

Views: 2012

Answers (2)

paxdiablo
paxdiablo

Reputation: 881363

I have two pieces of advice based on long experience with systems that did it badly :-)

The first is to not store date and time information as strings or integral values, especially when C++ has very good support for that in std::chrono. If you use the correct types, comparisons and manipulations become relatively simple.

Second, make sure you use UTC for all times. You should convert local times to UTC as soon as possible after getting them, and convert back to local as late as possible when presenting them. This will also greatly simplify comparisons.


By way of example, here's a complete program which show the simplicity(a) in action:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>

using std::chrono::system_clock;
using std::chrono::duration_cast;

namespace {
    system_clock::time_point getTimePoint(std::string strTime) {
        std::tm myTm = {};
        std::stringstream ss(strTime.c_str());
        ss >> std::get_time(&myTm, "%Y/%m/%d %H:%M");
        return system_clock::from_time_t(std::mktime(&myTm));
    }


    void outputTime(const char *desc, system_clock::time_point &tp) {
        std::time_t now = system_clock::to_time_t(tp);
        std::cout << desc
            << std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M") << "\n";
    }
}

int main() {
    std::string startTime = "2019/04/15 10:30";
    std::string endTime   = "2019/04/16 09:30";

    auto startTp = getTimePoint(startTime);
    auto endTp = getTimePoint(endTime);

    outputTime("Start time: ", startTp);
    outputTime("  End time: ", endTp);

    auto duration = duration_cast<std::chrono::minutes>(endTp - startTp);
    std::cout << "\nThere are " << duration.count() << " minutes between "
        << startTime << " and " << endTime << "\n";
}

The output of that program is:

Start time: 2019-04-15 10:30
  End time: 2019-04-16 09:30

There are 1380 minutes between 2019/04/15 10:30 and 2019/04/16 09:30

(a) Yes, the program may seem reasonably big but that's just because of the stuff making it a complete program. The getTimePoint and outputTime functions show how to do the conversion to and from time points, and the meat of the simplicity is the line containing duration_cast to get the number of minutes between the two time points.

Upvotes: 5

DevSolar
DevSolar

Reputation: 70263

The go-to place regarding dates and times in C++ is <chrono>. Some of it has been with us since C++11, some of it we'll see coming with C++20. It works in conjunction with the C-style date and time utilities in <ctime>, which might even suffice for your purposes.

Trying to handle date / time as either integers or strings, parsing them from input, comparing, and converting them to strings for output, will effectively result in you reimplementing parts of what's already in those headers (a.k.a. "reinventing the wheel").

Upvotes: 5

Related Questions