Я видел примеры для C #, Java, но для C ++ я не могу найти решение, чтобы посчитать, сколько дней между двумя датами.
Например, между 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
Преобразуйте даты в целое число, обозначающее количество дней с начала эпохи, затем вычтите. В этом примере я выбрал Rata Die, объяснение алгоритма можно найти на <http://mysite.verizon.net/aesir_research/date/rata.htm>.
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);
Новый ответ на старый вопрос:
Используя это C ++ 11 / C ++ 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() << " days\n";
}
Какие выводы:
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 эпоху), вы можете легко вычислить количество дней не только между любыми двумя датами, но и между любыми двумя календарями, которые вы смоделировали.
Это дает вам свободу без необходимости жестко кодировать дату для перехода с юлианского на григорианский. Вы просто должны знать, на какой календарь ссылаются ваши входные данные.
Иногда даты в исторических документах, которые могут быть неоднозначными, помечаются Старый Стиль / Новый Стиль указать юлианский или григорианский календарь соответственно.
Если вы также беспокоитесь о времени суток с вашими датами, это та же библиотека дат легко интегрируется с <chrono>
библиотека для использования hours
, minutes
, seconds
, milliseconds
, microseconds
а также nanoseconds
, и с system_clock::now()
чтобы получить текущую дату и время.
Если вы беспокоитесь о часовых поясах, дополнительный (отдельный) библиотека часовых поясов написано на вершине библиотека дат обрабатывать часовые пояса, используя База данных часовых поясов IANA. При необходимости библиотека часовых поясов также есть средство для вычислений, которые включают в себя високосные секунды.
Вы можете попробовать повысить дату и время библиотека
Чтобы не создавать свои собственные функции, вы можете использовать date_time от Boost.