Как обращаться со временем в C

#c

#c

Вопрос:

У меня есть вопрос об управлении датой и временем в c . В моей программе есть два класса Plane и Flight.

Моя плоскость будет состоять из данных в виде:

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

Мой класс полета будет содержать данные в виде:

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

В моем основном классе я буду вводить значения для DepartureDate и ArrivalDate в формате: «ГГГГ / ММ / ДД ЧЧ: ММ», например: "2019/04/15 10:30" and "2019/04/16 9:30" (я буду использовать 24-часовой формат, и время будет GMT).

Мой вопрос заключается в том, как мне преобразовать две приведенные выше строки в надлежащий формат для сохранения в моем planeSchedule, чтобы я мог избежать конфликта времени в planeSchedule.

Например, если в следующий раз я добавлю рейс с датой вылета и прибытия между: 2019/04/15 10:30" and "2019/04/16 9:30" , например: "2019/04/15 13:30" and "2019/04/16 7:30" , я получу сообщение об ошибке типа «Конфликт рейсов, самолет недоступен для полета».

Мой профессор рекомендует использовать unsigned long int для хранения времени, но я действительно не знаю, с чего начать, чтобы решить эту проблему. Приветствуется любая помощь / предложение.

Комментарии:

1. время обычно хранится в виде целого числа, которое представляет количество единиц (секунда, миллисекунда, 100 наносекунд и т.д.) от эпохи. Смотрите en.wikipedia.org/wiki/Unix_time#Encoding_time_as_a_number

2. en.cppreference.com/w/cpp/chrono

Ответ №1:

Основное место, касающееся дат и времени в C , является <chrono> . Кое-что из этого есть у нас с C 11, кое-что, как мы увидим, появится с C 20. Это работает в сочетании с утилитами даты и времени в <ctime> стиле C, которых может быть даже достаточно для ваших целей.

Попытка обработать дату / время либо в виде целых чисел, либо в виде строк, анализируя их из входных данных, сравнивая и преобразуя их в строки для вывода, эффективно приведет к тому, что вы переопределите части того, что уже есть в этих заголовках (также известное как «изобретение колеса»).

Комментарии:

1. Я поражен, что профессора на самом деле рекомендуют избитые вещи вроде «использовать беззнаковый long int для хранения времени», как будто это был 1970 год… неудивительно, что люди уходят с таких курсов, думая «C сложный», хотя на самом деле это не так.

2. Вот рабочий предварительный просмотр 20 <chrono> бит C : github.com/HowardHinnant/date Это находится в пространстве имен date вместо namespace std::chrono .

Ответ №2:

У меня есть два совета, основанных на многолетнем опыте работы с системами, которые делали это плохо 🙂

Первое — не хранить информацию о дате и времени в виде строк или целых значений, особенно когда C имеет очень хорошую поддержку для этого в std::chrono . Если вы используете правильные типы, сравнения и манипуляции становятся относительно простыми.

Во-вторых, убедитесь, что вы используете UTC для всех времен. Вы должны преобразовать местное время в UTC как можно скорее после их получения и преобразовать обратно в местное как можно позже при их представлении. Это также значительно упростит сравнения.


В качестве примера, вот полная программа, которая демонстрирует простоту (a) в действии:

 #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(amp;myTm, "%Y/%m/%d %H:%M");
        return system_clock::from_time_t(std::mktime(amp;myTm));
    }


    void outputTime(const char *desc, system_clock::time_point amp;tp) {
        std::time_t now = system_clock::to_time_t(tp);
        std::cout << desc
            << std::put_time(std::localtime(amp;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";
}
  

Результат этой программы является:

 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) Да, программа может показаться достаточно большой, но это только из-за материала, делающего ее полноценной программой. Функции getTimePoint и outputTime показывают, как выполнять преобразование в временные точки и из них, а суть простоты заключается в строке, содержащей duration_cast количество минут между двумя временными точками.

Комментарии:

1. Можете ли вы дать мне несколько инструкций по использованию std:: chrono для решения моей проблемы, я ценю все, что угодно.

2. @DatTo: Это было бы проще, если бы вы могли свести «вашу проблему» к одной единственной функциональности. В нынешнем виде «ваша проблема» — это все, начиная с синтаксического анализа входных данных и заканчивая сохранением значений и некоторым не очень четко определенным сравнением с выводом. Т.Е. «напишите мою программу для меня», что обычно не делается в Stackoverflow. Выберите что-нибудь конкретное, и я уверен, мы могли бы показать вам несколько строк примера кода.