C++ 获取两个日期之间的日期

C++ get dates between two dates

我把每个日期都放在一个结构向量中 (vector<value>) :

struct value {
    string code;
    string date;
    string name;
};

日期格式为"YYYY-MM-DD HH:MM:SS"

我想获取两个给定日期之间的日期(例如从 01/01/2016 到 01/02/2016)。我该怎么做?

在示例中,您可以这样做:将所有日期转换为 time_t 值(日期和时间的数字表示),然后遍历向量并使用三个 time_t 数字之间的正常比较.供参考:man mktime, man strptime.

这个问题是双重的:

  1. 如何从字符串表示中获取可排序的日期值
  2. 如何有效地对所述值进行排序。

从 date-string

中查找有效时间戳

C++ 使用 time_t 对象作为从设定日期(UTC 时间 1970 年 1 月 1 日)开始的有效秒数 There's plenty of concise information about that,在 every-case 中你可以认为这是一个 Integer-representation 以秒为单位的时间。

接下来您需要了解如何将数据解析为 time-stamp:这里有一些非常有用的链接。

我的首选方法是mktime - there's an example of that Here on stack-overflow. Also it seems someone else has done the same course as you ;)

您可能要考虑使用 A function of your own design, if the date format is unusual. In this case, using scanf 通常是最简单的方法 - 此函数的接口有点 old-school "c-style",但这并没有改变它的简单事实工作,很好。 Here's a link to someone reading a simple-date with scanf.

原来我下面写的代码接近The answer to this great question

#include <stdio.h>
#include <time.h>  
time_t GetDateFromObject(value & Date_Object)
{
    char * Date_String = Date_Object.date.c_str();
    int year, month, day, hour, minute, second;
    if(sscanf(Date_String , "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6)
    { 
        time_t rawTime;
        time(&rawTime);
        struct tm * parsedTime;
        parsedTime = localtime(&rawTime);

        // tm_year is years since 1900
        parsedTime->tm_year = year - 1900;
        // tm_months is months since january
        parsedTime->tm_mon = month - 1;
        parsedTime->tm_mday = day;
        parsedTime->tm_hour = hour;
        parsedTime->tm_min = minute;
        parsedTime->tm_sec = second;
        return mktime(parsedTime);
   }
}

日期的关联与排序

一旦您知道如何从您的约会中获取 time_t,您就可以开始创建数据的关联数组 - 在这种情况下,我将使用 map.

下面是一个使用地图插入、排序和输出数据的示例。

#include<iostream>
#include<map>
#include<vector>
#include<ctime>

struct value {
    std::string code;
    std::string date;
    std::string name;
};

void Print_Range(std::vector<value> & Data, value & Date_Start, value & Date_end)
{
    std::map<time_t, value *> Associated_Data;
    for(auto Date_Object : Array_Of_Dates)
    {
        time_t Object_Time = GetDateFromObject(Date_Object);
        Associated_Data.insert(std::make_pair(Object_Time, & Date_Object); 
    }
    //as the std::map is sorted by-default, 
    //we can know locate the iterator for any two time codes
    time_t Search_From = GetDateFromObject(Date_Start);
    time_t Search_To = GetDateFromObject(Date_End);
    auto Start_IT = Associated_Data.find(Search_From);
    auto End_IT = Associated_Data.find(Search_To);

    std::cout << "Printing all dates in range \n";
    for(auto IT=Start_IT; IT != End_IT; IT++)
    {
        std::cout << IT->Second->date << '\n';
    }
}

备注:

  1. 我在这里使用 C++11 语法,如果你不理解 Range based loops 你可能想阅读它们。
  2. 我假设您描述的结构存储在 vector.
  3. 我在这里使用的 "GetDateFromObject" 函数是您用来获取时间戳的任何函数的占位符)
  4. Inserting data into a map using std::make_pair.
  5. 我持有指向原始 value-objects 的指针。

日期格式YYYY-MM-DD HH:MM:SS的特殊之处在于字典顺序(逐个字母)比较与时间比较相同,因此您可以直接使用它。

如果您的容器最初没有按日期排序,您将不得不一个一个地检查所有日期。 std::copy_if 提供了一种很好的方法:

std::vector<value> get_between(const std::vector<value>& v,
        const std::string& from, const std::string& to)
{
    std::vector<value> u;
    std::copy_if(v.begin(), v.end(), std::inserter(u, u.begin()),
    [from,to](const auto& val) {
        return val.date >= from && val.date <= to;
    });
    return u;
}

copy_if 遍历 [v.begin(), v.end()[ 并在 lambda returns 为真时从 u.begin() 开始将元素插入 u。它们的顺序与您输入的顺序相同。

如果您的范围已排序,您可以使用 std::lower_boundstd::upper_bound 来获取开始和结束迭代器:

std::vector<value> get_between(const std::vector<value>& v,
        const std::string& from, const std::string& to)
{
    value fromv { "", from, "" };
    auto begin = std::lower_bound(v.begin(), v.end(), fromv,
    [](const auto& lhs, const auto& rhs) {
        return lhs.date < rhs.date;
    });

    value tov { "", to, "" };
    auto end = std::upper_bound(begin, v.end(), tov,
    [](const auto& lhs, const auto& rhs) {
        return lhs.date < rhs.date;
    });

    return std::vector<value>(begin, end);
}

lower_boundupper_bound求出的第一个值至少from的第一个值大于 to,因此范围 [lb, ub[ 是值为 [from, to].

的范围