如何在c ++中迭代日期范围

时间:2014-01-31 04:10:12

标签: c++ date loops iteration

我有一个包含csv文件的文件夹。每个csv文件由日期命名(例如,01JAN2013.csv,02JAN2013.csv)。我必须按照日期的顺序阅读文件(开始日期和结束日期已知)。

所以我试图遍历从开始日期到结束日期的日期,以生成文件名。

目前我在做:

vector<string> dd{"01", "02", "03", "04", "05", "06", "07", "08", "09","10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20","21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"};
vector<string> mmm{"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG","SEP", "OCT", "NOV", "DEC"};
vector<string> yyyy{"2011","2012","2013","2014"};

string filePath=DataFolderPath;

for(int i=0;i<yyyy.size();i++)
{
    for(int j=0;j<mmm.size();j++)
    {
        for(int k=0;k<dd.size();k++)
        {
            filePath.append(dd[k]);
            filePath.append(mmm[j]);
            filePath.append(yyyy[i]);
            filePath.append(".csv");
        }
    }
}

绝对丑陋,但它完成了工作。

是否有更简单的方法在C ++中循环日期。有点像:

for ( currentDate = starDate; currentDate < endDate; currentDate++) {

//Do stuff

 }

更新:

这是我最终使用的方法,结合以下两个答案:

typdef struct tm Time;
Time startDate=makeDate(3,1,2011);
Time endDate=makeDate(24,1,2014);
time_t end=mktime(&endDate);

for(Time date=startDate;end>=mktime(&date);++date.tm_mday)
{
    char buffer[16];
    strftime(buffer, sizeof(buffer), "%d%b%Y.csv", &date);

    std::string filename(buffer);
            //To convert month to CAPS
    std::transform(filename.begin()+2, filename.begin()+5,filename.begin()+2, ::toupper);


    std::cout << filename << "\n";
}

我还使用了基于paddy答案的makeDate辅助函数,该函数返回struct tm而不是time_t

Time makeDate( int day, int month, int year )
{
Time ttm = {0};
ttm.tm_mday= day;
ttm.tm_mon= month-1;
ttm.tm_year= year-1900;
return ttm;
}

3 个答案:

答案 0 :(得分:6)

实际上可能并不容易....但您可以使用<ctime>中的时间函数。像这样:

string MakeFileName( time_t t )
{
    static const char* months[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
                                    "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
    struct tm *ptm = localtime(&t);

    char buffer[20];
    snprintf( buffer, 20, "%02d%s%04d.CSV",
              ptm->tm_day, months[ptm->tm_month], ptm->tm_year+1900 );

    return string(buffer);
}

现在只需在time_t值中确定您的开始日期和结束日期(请记住,它以秒为单位)。您可以暂时使用00:00:00

// Note that day and month are 1-based.
time_t GetDate( int day, int month, int year )
{
    struct tm ttm = {0};
    ttm.tm_day = day;
    ttm.tm_month = month-1;
    ttm.tm_year = year-1900;
    return mktime(&ttm);
}

使用该助手,您可以轻松设置开始日期和结束日期:

time_t start = GetDate(1, 1, 2011);
time_t end = GetDate(28, 10, 2013);
for( time_t t = start; t <= end; t += 86400 )
{
    string filename = MakeFileName(t);

    // TODO...
}

答案 1 :(得分:2)

如果您决定生成名称,我认为@paddy有正确的总体思路,但实施可能会有一些改进。特别是,mktime不仅可以进行转换,而且可以...修复其输入,因此如果您给它输入2月30日,它知道3月1日或2日,并将适当地更改它。同样,它知道32 December 2011确实是1 Jan 2012并且(再次)适当地调整输入。

猜测一下,你也可能真的不希望在未来生成日期,并且只是在年底生成日期,因为你不想在每个日期修改日期。我猜测只是在它运行的日期生成日期可能就足够了。

考虑到这些,我会更像这样编写代码:

#include <time.h>
#include <iostream>

int main() {
    struct tm date;

    date.tm_mon = 1;
    date.tm_mday = 1;
    date.tm_year = 2011 - 1900;

    time_t end = time(NULL);

    for (; mktime(&date) < end; ++date.tm_mday) {
        char buffer[16];

        strftime(buffer, sizeof(buffer), "%d%b%Y", &date);
        std::cout << buffer << "\t";
    }
}

目前这只打印出字符串,但如果正确生成它们,将它们用作文件名通常会非常简单。

如果你想按照我在评论中的建议去做,并获取所有文件名,然后按日期排序,你可以将每个文件名转换为time_t,排序{{1 }}秒。一个相当简单的方法是使用time_t操纵器:

std::get_time

有了这个,您可以(有一种可能性)将time_t cvt(std::string const &filename) { std::istringstream in(filename); struct tm date; in >> std::get_time(&date, "%d%b%Y"); return mktime(date); } 和文件名放入time_t,然后从头到尾遍历地图,并按顺序处理每个文件。

std::map

答案 2 :(得分:2)

#include <boost/date_time.hpp>

using namespace boost::gregorian;

long dateDifference( string start_date, string end_date ) 
{
    date _start_date(from_simple_string(start_date));
    date _end_date(from_simple_string(end_date));

    for(day_iterator iter = _start_date; iter!=_end_date; ++iter)
    {
       // Do what you want
    }
}