生成随机日期

时间:2013-11-28 16:45:43

标签: c++ date random time

我编写了这段代码片段来生成随机日期:

std::time_t curr_time = time(0);
std::time_t ten_years = 365 * 12 * 30 * 24 * 60;
std::time_t rand_date = curr_time - std::rand() % ten_years;
tm *ltm = std::localtime(&rand_date);
std::cout << ltm->tm_year + 1900 << " " << ltm->tm_mon + 1 << " " << ltm->tm_mday << std::endl;

然而它总是给我当前日期。我做错了什么?

6 个答案:

答案 0 :(得分:5)

std :: rand()可能返回相当小的值,0..32767是最小范围,并且在一些流行的32位平台(其中包括MSVC)中这样做。使用time_t以秒为单位,这只会给你大约8小时的随机噪音。

尝试组合来自一对std :: rand调用的结果。例如。 (std::time_t) std::rand() * RAND_MAX + std::rand()或切换到更好的随机数生成器。

答案 1 :(得分:2)

我建议您不要直接修改time_t,因为标准没有指定实现。最好将其转换为这个问题:How to add one day to a time obtained from time()

答案 2 :(得分:2)

我建议根据CPP参考文献以不同方式进行:

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

using namespace std;

int main() {
    time_t timer;
    struct tm x_years;
    struct tm* current;
    int how_many_years = 10;
    srand (time(NULL));
    int randomYear = (rand()%how_many_years)+1;
    int randomMonth = (rand()%12)+1;
    int randomDays = (rand()%30)+1;


    time(&timer);  /* get current time; same as: timer = time(NULL)  */
    current = localtime(&timer);
    x_years.tm_hour = 0;
    x_years.tm_min = 0;
    x_years.tm_sec = 0;
    x_years.tm_year = current->tm_year - randomYear;
    x_years.tm_mon = (current->tm_mon - randomMonth) <= 0 ? current->tm_mon + (12-randomMonth) : current->tm_mon - randomMonth;
    x_years.tm_mday = (current->tm_mday - randomDays) <= 0 ? current->tm_mday + (30-randomDays) : current->tm_mday - randomDays;

    //returns seconds ever since the random generated date until now
    cout << "Years rolled back: " << randomYear << endl;
    cout << "Months rolled back: " << randomMonth << endl;
    cout << "Days rolled back: " << randomDays << endl;
    cout << endl;
    cout << "Current Year: " <<  current->tm_year+1900 << endl;
    cout << "Current Month: " <<  current->tm_mon << endl;
    cout << "Current Day: " <<  current->tm_mday << endl;
    cout << endl;
    cout << "Year: " <<  x_years.tm_year+1900 << endl;
    cout << "Month: " <<  x_years.tm_mon << endl;
    cout << "Day: " <<  x_years.tm_mday << endl;
}

修改

我已经编辑了代码,有了它,你甚至可以选择你想要回去多少年。基本上,你回到X年的时间,你可以在x_years结构中回滚日期。

希望这有帮助!

答案 3 :(得分:1)

以下解决方案使用带有内部uniform_int_distribution的C ++ 11:

// uniform_time_dist.h
#include <chrono>
#include <random>

template <class TimePoint>
class uniform_time_distribution{
public:
  uniform_time_distribution(TimePoint start, TimePoint end)
    : m_start(start), m_end(end),
    m_seconds(std::chrono::duration_cast<std::chrono::seconds>(end - start))
  {}

  template <class Generator>
  TimePoint operator()(Generator && g){
    std::uniform_int_distribution<std::chrono::seconds::rep> d(0, m_seconds.count());

    return m_start + std::chrono::seconds(d(g));
  }

private:
  TimePoint m_start;
  TimePoint m_end;
  std::chrono::seconds m_seconds;
};

您可以像使用生成器的任何其他distribution function一样使用它:

// uniform_time_dist.h -- continuation 
template <class TimePoint>
TimePoint randomTime(TimePoint start, TimePoint end){
  static std::random_device rd;
  static std::mt19937 gen(rd());

  uniform_time_distribution<TimePoint> t(start, end);

  return t(gen);
}

您可以使用time_t

将此方法与clock::to_time_t功能结合使用
#include <iostream>
#include "uniform_time_dist.h" // see above

using namespace std::chrono;

int main(){
  auto k = system_clock::to_time_t(randomTime(
    system_clock::now(),
    system_clock::now() + hours(24 * 365 * 10)));

  std::cout << std::ctime(&k);    
}

请注意,上面的类只是一个小草图,您应该能够大大改进它以匹配其他分布函数。

答案 4 :(得分:0)

我设法根据Phil的回答创建了一个解决方案:

time_t currTime = time(0);
tm *ltm = std::localtime(&currTime);
ltm->tm_mday = std::rand() % 3650 * -1;
time_t next = mktime(ltm);
ltm = std::localtime(&next);
std::cout << ltm->tm_year + 1900 << " " << ltm->tm_mon + 1 << " " << ltm->tm_mday << std::endl;

答案 5 :(得分:0)

如果您正在使用boost库,您可以使用我编写的这个类来获取随机日期:

#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"


using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;


class Randomizer {
private:
    static const bool debug_mode = false;
    random::mt19937 rng_;

    // The private constructor so that the user can not directly instantiate
    Randomizer() {
        if(debug_mode==true){
            this->rng_ = random::mt19937();
        }else{
            this->rng_ = random::mt19937(current_time_nanoseconds());
        }
    };

    int current_time_nanoseconds(){
        struct timespec tm;
        clock_gettime(CLOCK_REALTIME, &tm);
        return tm.tv_nsec;
    }

    // C++ 03
    // ========
    // Dont forget to declare these two. You want to make sure they
    // are unacceptable otherwise you may accidentally get copies of
    // your singleton appearing.
    Randomizer(Randomizer const&);     // Don't Implement
    void operator=(Randomizer const&); // Don't implement

public:
    static Randomizer& get_instance(){
        // The only instance of the class is created at the first call get_instance ()
        // and will be destroyed only when the program exits
        static Randomizer instance;
        return instance;
    }
    bool method() { return true; };

    int rand(unsigned int floor, unsigned int ceil){
        random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
        return (rand_(rng_));
    }

    // Is not considering the millisecons
    time_duration rand_time_duration(){
        boost::posix_time::time_duration floor(0, 0, 0, 0);
        boost::posix_time::time_duration ceil(23, 59, 59, 0);
        unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
        return seconds(rand_seconds);
    }


    date rand_date_from_epoch_to_now(){
        date now = second_clock::local_time().date();
        return rand_date_from_epoch_to_ceil(now);
    }

    date rand_date_from_epoch_to_ceil(date ceil_date){
        date epoch = ptime(date(1970,1,1)).date();
        return rand_date_in_interval(epoch, ceil_date);
    }

    date rand_date_in_interval(date floor_date, date ceil_date){
        return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
    }

    ptime rand_ptime_from_epoch_to_now(){
        ptime now = second_clock::local_time();
        return rand_ptime_from_epoch_to_ceil(now);
    }

    ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
        ptime epoch = ptime(date(1970,1,1));
        return rand_ptime_in_interval(epoch, ceil_date);
    }

    ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
        time_duration const diff = ceil_date - floor_date;
        long long gap_seconds = diff.total_seconds();
        long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
        return floor_date + seconds(step_seconds);
    }
};