2013-04-05 4 views
3

Это смущает, но мне трудно делать простые манипуляции с датами.Как управлять датами/датами в C++ 11?

Это версия C#, которую я в основном стараюсь использовать с помощью C++ 11;

DateTime date1=new DateTime(4,5,2012); 
DateTime date2=new DateTIme(7,8,2013); 
int day1=date1.Days; 
TimeSpan ts=d2-d1; 
int diffDays=ts.Days; 

Что я попробовал?

std::tm tm; 
    tm.tm_year=113; 
    tm.tm_mon=0; 
    tm.tm_wday=0; 

    std::time_t tt=mktime(&tm); 
    std::chrono::system_clock::time_point then = std::chrono::system_clock::from_time_t(tt); 
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); 
    auto e1 = std::chrono::duration_cast<std::chrono::hours>(now - then).count(); 

Величина e1 (379218) не имеет значения, что так когда-либо.

Я взглянул на хронограф, который представлен как стандартная библиотека C++ 11 для datetime, но я просто не мог найти пример того, как создать дату с int year = 2012, int month = 2, int день = 14.

PS: Хроно достаточно для обработки даты/времени/часовых поясов в C++ 11? Есть ли потребность в time.h?

+1

'' имеет дело со временем, но это не касается календарей, которые вы ищете (кроме преобразования из 'time_t'). Я еще не знаю каких-либо библиотек календарей, построенных поверх ''. –

+3

Для обработки дат существует отличная библиотека 'boost gregorian': http://www.boost.org/doc/libs/1_39_0/doc/html/date_time/gregorian.html. Кроме того, QT имеет собственные классы дат. – decden

+3

В дополнение к хорошему предложению использовать библиотеку boost, вы можете попробовать мою библиотеку дат, описанную в этом SO-ответе: http://stackoverflow.com/a/15146434/576911. Вот прямая ссылка на него: http://home.roadrunner.com/~hinnant/bloomington/date.html –

ответ

2

Вы должны инициализировать все поля из tm, начните с

std::tm tm = {0,0,0,0,0,0,0,0,0,0,0}; 

Без этого, остальные поля (те, которые вы явно не установлены впоследствии) будет содержать произвольные значения. Преобразование также нормализует значения, а это означает, что если поле tm_hour содержит 123456789, оно добавит столько часов до указанного вами дня. Вот как можно объяснить эти бессмысленные значения для e1. Если вы инициализируете все поля явно, это позволит вашему примеру возвращать значимые значения, хотя вам может потребоваться установить больше полей, например isdst, чтобы сделать его правильным для всех случаев.

Я должен признать, что я не использовал chrono, поскольку я нахожу требуемый синтаксис слишком многословным, и я продолжаю использовать свои собственные классы для переноса функций времени в стиле C. Это, конечно, не утверждение о качестве и мощности <chrono>, может быть, я должен начать использовать его :)

+0

Не можете ли вы просто сделать 'std :: tm tm = {0}'? – 0x499602D2

+0

@ 0x499602D2 Да, но оба GCC и Clang предупредит вас о пропавших инициализаторах полей, см. [LWS] (http://liveworkspace.org/code/2CAxKb$0). –

+0

@ Даниэль: Но я подозреваю, что 'std :: tm tm = {};' не будет. – ildjarn

5

Новый ответ на старый вопрос.

За исключением беспорядка с архаичным std::tm, C++ 11 не имеет хороших способов иметь дело с датами или датами, за исключением boost Date Time. И есть еще одна библиотека, над которой я работал в последнее время, которая сильно зависит от производительности, безопасности типа компиляции и совместимости chrono. Как представлено, он работает только с C++ 14, но если вы отмените некоторые из constexpr, он будет работать с C++ 11. Он имеет только заголовок и состоит только из одного заголовка и документирован here. Он светлый от возможности ввода-вывода. (и теперь имеет расширенные возможности ввода/вывода)

Но вот как это выглядит для примера:

О, теперь, когда я смотрю внимательно, и не зная, C#, я не знаю, является ли DateTime(4,5,2012) относится к 5 апреля 2012 года или 4 мая 2012 года. Используются как форматы m/d/y, так и d/m/y. Это одна из проблем моих адресов библиотек. Он принимает оба формата недвусмысленно. Для этой демонстрации я собираюсь предположить, что вы пишете в формате m/d/y.Но я буду использовать оба формата, чтобы воспроизвести ваш пример:

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

int 
main() 
{ 
//  DateTime date1=new DateTime(4,5,2012); 
//  DateTime date2=new DateTIme(7,8,2013); 
//  int day1=date1.Days; 
//  TimeSpan ts=d2-d1; 
//  int diffDays=ts.Days; 

    using namespace date; 
    auto date1 = sys_days(apr/5/2012);  // m/d/y is ok 
    auto date2 = sys_days(8_d/jul/2013); // d/m/y is ok 
              // y/m/d is also ok 
    auto diffDays = date2 - date1;   // diffDays is a chrono::duration 
    std::cout << diffDays.count() << '\n'; 
} 

Это будет:

459 

И в C++ 14, это вычисление на самом деле может быть сделано во время компиляции:

constexpr auto date1 = sys_days(apr/5/2012); 
constexpr auto date2 = sys_days(8_d/jul/2013); 
constexpr auto diffDays = date2 - date1; 
static_assert(diffDays == days{459}, ""); 

И это означает, что «константы даты» могут быть как очень читабельными, так и очень эффективными, скомпилировавшись до «непосредственной нагрузки».

См. the documentation для полного описания, руководства и реализации.