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

时间:2016-01-26 08:46:53

标签: c++ sorting date-range

我将每个日期都放在struct (vector<value>)的向量中:

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

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

我希望在两个给定日期之间获取日期(例如2016年1月1日至2016年2月1日)。我怎么能这样做?

3 个答案:

答案 0 :(得分:2)

日期格式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返回true,就会从u开始将元素隐藏到u.begin()中。它们的顺序与你给它们的顺序相同。

如果您的范围已排序,则可以使用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的第一个值 {{1} }},以便范围to是值为[lb, ub[的范围。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

这个问题有两个方面:

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

    中查找有效时间戳

    C ++使用time_t对象作为设定日期(1970年1月1日)There's plenty of concise information about that的有效秒数,在每种情况下,您可以将其视为以秒为单位的整数表示。

    接下来,您需要知道如何将数据解析为时间戳:这里有一些相当有用的链接。

    我首选的方法是mktime - 这是Here on stack-overflow的一个例子。它也是seems someone else has done the same course as you ;)

    如果日期格式不正常,您可能需要考虑使用A function of your own design。在这种情况下,使用scanf通常是最简单的方法 - 这个函数的界面有些老派“c风格”,但这并没有改变它运作的简单事实,而且很好。 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. 我持有指向原始值对象的指针。