2017-10-19 112 views
0

我已經構建了一個函數,它將輸入一個特定日期並以std::chrono::milliseconds格式返回此日期。我們可以從一個相同類型的範圍中獲取一個`std :: chrono :: milliseconds`變量嗎?

milliseconds lowerRangeBound = TimeStamp(mm, dd, HH, MM, SS, yyyy); 

例如,

milliseconds a = TimeStamp(8/*month*/, 23/*day*/, 14/*hours*/, 46/*minutes*/, 32/*seconds*/, 2017/*year*/); 

返回一個轉換後的字符串格式:2017.08.23-14.46.32

我現在想要做什麼和不工作給出兩個日期(milliseconds)採取隨機日期在這兩個日期定義的範圍內。例如,給定

milliseconds a = TimeStamp(8/*month*/, 23/*day*/, 13/*hours*/, 46/*minutes*/, 32/*seconds*/, 2017/*year*/); 
milliseconds b = TimeStamp(10/*month*/, 23/*day*/, 13/*hours*/, 46/*minutes*/, 32/*seconds*/, 2017/*year*/); 

預期輸出是milliseconds c其中以字符串格式是這樣的日期,2017.09.13-12.56.12。請注意,所需的輸出是milliseconds,提供的字符串格式是爲了在readable format中發言。

我迄今試圖爲每個milliseconds變量轉換成long號(.count()),並獲得範圍[a,b]一個randomlong。但是,輸出日期無關緊要:1977.12.06-16.27.02

請問你能幫忙嗎?

預先感謝您。

編輯:代碼波紋管是由該link

milliseconds TimeStamp(int mm, int dd, int HH, int MM, int SS, int yyyy) { 

    tm ttm = tm(); 
    ttm.tm_year = yyyy - 1900; // Year since 1900 
    ttm.tm_mon = mm - 1; // Month since January 
    ttm.tm_mday = dd; // Day of the month [1-31] 
    ttm.tm_hour = HH; // Hour of the day [00-23] 
    ttm.tm_min = MM; 
    ttm.tm_sec = SS; 

    time_t ttime_t = mktime(&ttm); 
    system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(ttime_t); 
    milliseconds now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(time_point_result).time_since_epoch(); 
    return now_ms; 
} 

milliseconds getRandomTimestamp(int mm_1, int dd_1, int HH_1, int MM_1, int SS_1, int yyyy_1, 
    int mm_2, int dd_2, int HH_2, int MM_2, int SS_2, int yyyy_2, int N) { 

    milliseconds lowerRangeBound = fixedTimeStamp(mm_1, dd_1, HH_1, MM_1, SS_1, yyyy_1); 
    milliseconds upperRangeBound = fixedTimeStamp(mm_2, dd_2, HH_2, MM_2, SS_2, yyyy_2); 

    long lowerRange_ = lowerRangeBound.count(); 
    long upperRange_ = upperRangeBound.count(); 

    //long output = rand() % (upperRange_ - lowerRange_ + 1) + lowerRange_; 
    // rand() replaced after @Jarod42's suggestion. 
    std::default_random_engine generator; 
    std::uniform_int_distribution<int> distribution(lowerRange_, upperRange_); 
    long output = distribution(generator);   

    std::chrono::duration<long> dur(output); 
    return dur; 
} 
+1

*您嘗試了什麼*請向我們展示一個[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve),而不是僅僅描述它。 –

+2

題外話到你的問題:'myTimeStamp(8,23,13,46,32,2017);'是一個可怕的頭痛,容易出錯的設計 – bolov

+0

我希望現在的帖子更具吸引力。順便感謝您的關注! – Darkmoor

回答

2

啓發這可能是你要帶的,因爲混合關注數學混淆。

我建議你以毫秒爲單位編寫你的「隨機時間戳」程序。

您可以在單獨的步驟中執行從/到時間戳的轉換。

我會寫的程序是這樣的:

#include<random> 
#include<chrono> 
#include<cassert> 
#include<iostream> 

template<class Eng> 
std::chrono::milliseconds getRandomTimestamp(Eng& eng, 
              std::chrono::milliseconds low, 
              std::chrono::milliseconds high) 
{ 
    // deduce the actual integer type. 
    // Otherwise we'll have to guess what T is when using 
    // uniform_int_distribution<T> 
    using count_type = decltype(low.count()); 

    // from this we can deduce the correct integer distribution 
    using dist_type = std::uniform_int_distribution<count_type>; 

    // create the distribution generator 
    auto dist = dist_type(low.count(), high.count()); 

    // and apply it to the random generator, returning 
    // milliseconds somewhere between low and high 
    return std::chrono::milliseconds(dist(eng));  
} 


int main() 
{ 
    using namespace std::literals; 

    std::random_device dev; 
    std::default_random_engine eng(dev()); 

    auto t1 = 10'000'000ms; 
    auto t2 = 11'000'000ms; 
    auto t3 = getRandomTimestamp(eng, t1, t2); 

    assert(t1 <= t3); 
    assert(t3 <= t2); 

    std::cout << t1.count() << std::endl; 
    std::cout << t2.count() << std::endl; 
    std::cout << t3.count() << std::endl; 
} 
+0

感謝您的關注! – Darkmoor

1

,如果你採取的Howard Hinnant's free, open-source header-only date/time library優勢可以使這要容易得多。語法簡潔,非常易讀。例如,您可以使用date::sys_time<std::chrono::milliseconds>創建任何精度的chrono::time_point s(例如milliseconds)。

由於您的問題涉及time_point s而不是durations s,從類型安全的角度來看,這是更好的方法。下面是編寫getRandomTimestamp一種方法:

#include "date/date.h" 
#include <iostream> 
#include <random> 

date::sys_time<std::chrono::milliseconds> 
getRandomTimestamp(date::sys_time<std::chrono::milliseconds> lowerBound, 
        date::sys_time<std::chrono::milliseconds> upperBound) 
{ 
    static std::default_random_engine generator; 
    using namespace std::chrono; 
    std::uniform_int_distribution<milliseconds::rep> distribution{ 
     lowerBound.time_since_epoch().count(), 
     upperBound.time_since_epoch().count()}; 
    return date::sys_time<milliseconds>{milliseconds{distribution(generator)}}; 
} 

現在你唯一的問題是如何創造這些time_point小號!這真可謂是微不足道的:

int 
main() 
{ 
    using namespace date::literals; 
    using namespace std::chrono_literals; 
    auto t1 = date::sys_days{2017_y/8/23} + 13h + 46min + 32s; 
    auto t2 = date::sys_days{2017_y/10/23} + 13h + 46min + 32s; 
    auto t3 = getRandomTimestamp(t1, t2); 
    // ... 
} 

以上date::sys_days只是另一個chrono::time_point但隨着days而不是milliseconds(它本來也可以拼寫date::sys_time<date::days>)精度。並且2017_y/8/23是類型date::year_month_day的文字,意思是2017.08.23。

我利用了C++ 14的計時文字。如果您使用C++ 11,則需要使用hours{13}代替13h

最後,您可以格式和多種格式很容易流出來t3,例如:

std::cout << date::format("%Y.%m.%d-%T", t3) << '\n'; 

這只是對我輸出:

2017.09.04-17:14:04.220 

如果您有運行 - 時間積分值而不是文本作爲輸入,即易於處理,以及:

using namespace date; 
auto t1 = sys_days{year{y}/m/d} + hours{h} + ... 

如果你需要得到任何字段值的出t3,這也很容易,比如:

sys_days sd = floor<days>(t3); 
time_of_day<milliseconds> tod(t3-sd); 
year_month_day ymd = sd; 

ymd對年,月,日的getter和tod具有時,分干將,秒和毫秒(後者拼寫爲subseconds)。

相關問題