2015-07-19 10 views
1

Я пишу приложение, которое нуждается в возможности сравнить две даты. Это то, что у меня есть до сих пор:C++ - сравните две даты

struct entry { 
    string text; 
    string date; // format: dd.mm.yyyy 
    bool finished; 
}; 

string addNulls(int number, int cols) { 
    string num = to_string(number); 
    if (num.size() < cols) { 
     int count = cols - num.size(); 
     for (int i = 0; i < count; i++) { 
      num = "0" + num; 
     } 
    } 
    return num; 
} 

// [...] 

entry e = {"here is some text", "21.03.2019", false}; 

int day2 = atoi(e.date.substr(0, 2).c_str()); 
int month2 = atoi(e.date.substr(3, 2).c_str()); 
int year2 = atoi(e.date.substr(6, 4).c_str()); 

time_t t = time(0); 
struct tm * now = localtime(&t); 

string date1 = e.date.substr(6, 4) + "-" + e.date.substr(3, 2) + "-" + e.date.substr(0, 2) + " 00:00:00"; 
string date2 = addNulls(now->tm_year, 4) + "-" + addNulls(now->tm_mon, 2) + "-" + addNulls(now->tm_mday, 2) + " 00:00:00"; 

if(date2 > date1) { 
    // do something 
} 

код получает структуру «запись», которая содержит дату. Затем код сравнивает дату с фактическим временем. Проблема в том, что это не сработает! Я запускаю некоторые тесты с некоторым примером контента, но результат (date2> date1) возвращает false.

Почему?

Я прочитал это: C++ compare to string dates

+0

Для сравнения двух дат нет определенного 'operator>' for 'std :: string'. Чего ты ожидал? –

+1

@ πάνταῥεῖ Однако, если вы представляете две даты в формате ISO «ГГГГ-ММ-ДД», то лексикографическое сравнение таких строк также происходит правильно. –

+1

'tm_year' - текущий год минус 1900; например 2015 год представлен как 105. Аналогичным образом, 'tm_month' основан на нулевом значении: 0 за январь, 11 декабря. Если бы вы попытались выполнить минимальную отладку и фактически просмотрели содержимое «date1» и «date2» перед сравнением, вы бы это заметили сами. –

ответ

2

Я не отвечаю на ваш вопрос. Однако я предлагаю вам решение. Вы считали библиотеку даты и времени? Boost datetime очень популярен.

Если вы компилируете в C++ 11 или более поздней версии, я рекомендую этот date time library, так как он только заголовок (исключая необходимость ссылки на библиотеку, такую ​​как boost), и, на мой взгляд, он имеет более чистый синтаксис (это очень субъективная и предвзятая точка зрения).

Эта последняя библиотека построена на библиотеке C++ 11 <chrono>. Вот ваш пример кода с использованием этой библиотеки:

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

struct entry { 
    std::string text; 
    date::year_month_day date; 
    bool finished; 
}; 

int 
main() 
{ 
    entry e = {"here is some text", date::day(21)/3/2019, false}; 
    auto day2 = e.date.day(); 
    auto month2 = e.date.month(); 
    auto year2 = e.date.year(); 
    auto t = std::chrono::system_clock::now(); 
    auto date1 = date::sys_days{e.date}; 
    auto date2 = t; 
    if (date2 > date1) 
     std::cout << "It is past " << e.date << '\n'; 
    else 
     std::cout << "It is not past " << e.date << '\n'; 
} 

который в настоящее время выводит:

It is not past 2019-03-21 

В C++ 14, хроно литералы сделать задания буквальных раз очень компактен:

using namespace std::literals; 
auto date1 = date::sys_days{e.date} + 0h + 0min + 0s; 

Также по теме литералов вы можете сделать конструкцию entry немного более компактной, если вы заглянете в using namespace date;:

entry e = {"here is some text", 21_d/3/2019, false}; 

Повторное использование класса даты или даты и времени, а также создание собственного, проще, чем использование строки для хранения даты. Кроме того, вы получаете тип безопасности, чтобы случайно не добавить строку к дате, когда вы хотели добавить продолжительность времени к моменту времени.

0

Почему бы вам не использовать strptime разобрать ваши строки даты, конвертировать их в Эпохе, а затем сравнить?

#include <time.h> 

char * 
strptime(const char *restrict buf, const char *restrict format, 
    struct tm *restrict tm); 
+0

Есть несколько причин не делать этого. Например, (1) это не стандартный C++ и (2) это C-ориентированный указатель. –

+0

Согласовано, но @Paul уже использовал 'localtime' и' time', которые C-центричны (фактически определены в том же заголовке 'time.h' как' strptime'). – themoondothshine

+0

Это не технически правильно. '' является стандартным заголовком C++. 'strptime' является ** нестандартным ** расширением содержимого этого заголовка. Дополнительная информация: http://stackoverflow.com/questions/321849/strptime-equivalent-on-windows –

Смежные вопросы