Вопрос:
Я видел примеры для С#, Java, но для С++ я не могу найти решение для вычисления количества дней между двумя датами.
Например, между 2012-01-24 и 2013-01-08
Спасибо!
Лучший ответ:
Это один из способов.
#include <iostream> #include <ctime> int main() { struct std::tm a = {0,0,0,24,5,104}; /* June 24, 2004 */ struct std::tm b = {0,0,0,5,6,104}; /* July 5, 2004 */ std::time_t x = std::mktime(&a); std::time_t y = std::mktime(&b); if ( x != (std::time_t)(-1) && y != (std::time_t)(-1) ) { double difference = std::difftime(y, x) / (60 * 60 * 24); std::cout << std::ctime(&x); std::cout << std::ctime(&y); std::cout << «difference = » << difference << » days» << std::endl; } return 0; }
мой вывод
Thu Jun 24 01:00:00 2004 Mon Jul 05 01:00:00 2004 difference = 11 days
Вот ссылка на исходный авторский пост
Ответ №1
Преобразуйте даты в целое число, обозначающее количество дней с эпохи, а затем вычитайте. В этом примере я выбрал Rata Die, объяснение алгоритма можно найти в < .
int rdn(int y, int m, int d) { /* Rata Die day one is 0001-01-01 */ if (m < 3) y—, m += 12; return 365*y + y/4 — y/100 + y/400 + (153*m — 457)/5 + d — 306; } int days = rdn(2013, 1, 8) — rdn(2012, 1, 24); Ответ №2
Новый ответ на старый вопрос:
Используя эту С++ 11/С++ 14 только для записи даты, теперь вы можете написать:
#include «date.h» #include <iostream> int main() { using namespace date; using namespace std; auto x = 2012_y/1/24; auto y = 2013_y/1/8; cout << x << ‘n’; cout << y << ‘n’; cout << «difference = » << (sys_days{y} — sys_days{x}).count() << » daysn»; }
Какие выходы:
2012-01-24 2013-01-08 difference = 350 days
Если вы не хотите зависеть от этой библиотеки, вы можете написать свой собственный, используя те же алгоритмы даты, что и используемая библиотека даты. Они найдены в этой статье: хроно-совместимые алгоритмы даты низкого уровня. Алгоритм из этой статьи, который реализуется в этом примере, таков:
// Returns number of days since civil 1970-01-01. Negative values indicate // days prior to 1970-01-01. // Preconditions: y-m-d represents a date in the civil (Gregorian) calendar // m is in [1, 12] // d is in [1, last_day_of_month(y, m)] // y is «approximately» in // [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366] // Exact range of validity is: // [civil_from_days(numeric_limits<Int>::min()), // civil_from_days(numeric_limits<Int>::max()-719468)] template <class Int> constexpr Int days_from_civil(Int y, unsigned m, unsigned d) noexcept { static_assert(std::numeric_limits<unsigned>::digits >= 18, «This algorithm has not been ported to a 16 bit unsigned integer»); static_assert(std::numeric_limits<Int>::digits >= 20, «This algorithm has not been ported to a 16 bit signed integer»); y -= m <= 2; const Int era = (y >= 0 ? y : y-399) / 400; const unsigned yoe = static_cast<unsigned>(y — era * 400); // [0, 399] const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365] const unsigned doe = yoe * 365 + yoe/4 — yoe/100 + doy; // [0, 146096] return era * 146097 + static_cast<Int>(doe) — 719468; }
Подробнее см. хронологически совместимые алгоритмы даты низкого уровня, чтобы узнать, как работает этот алгоритм, модульные тесты для него и его диапазон действия.
Этот алгоритм моделирует пролептографический григорианский календарь, который расширяет григорианский календарь неограниченно, как вперед, так и назад. Чтобы моделировать другие календари (например, юлианский календарь), вам понадобятся другие алгоритмы такие как показанные здесь. Как только у вас есть другие календари, настроенные и синхронизированные с той же последовательной эпохой (эти алгоритмы используют 1970-01-01 григорианский, который также является Unix time epoch), вы можете легко вычислить количество дней не только между любыми двумя датами, но и между любыми двумя календарями, которые вы смоделировали.
Это дает вам свободу в том, что вам не нужно жестко кодировать дату перехода от юлианского к григорианскому. Вам просто нужно знать, к какому календарю привязаны ваши входные данные.
Иногда даты в исторических документах, которые в противном случае были бы двусмысленными, аннотируются с помощью Старый стиль/Новый стиль, чтобы указать календарь Джулиана или Григория соответственно.
Если вы также обеспокоены временем дня с вашими датами, эта библиотека тем же самым образом легко интегрируется с библиотекой <chrono> для использования hours, minutes, seconds, milliseconds, microseconds и nanoseconds и system_clock::now(), чтобы получить текущую дату и время.
Если вас беспокоят часовые пояса, дополнительная (отдельная) часовая зона написана поверх date для обработки часовых поясов с использованием базы данных часовых поясов IANA. Если необходимо, библиотека часовых поясов также имеет средство для вычислений, которое включает секунды прыжка.
Ответ №3
вы можете попробовать boost date_time библиотека
Ответ №4
Чтобы избежать создания собственной функции, вы можете использовать date_time из Boost.