3

std::gmtime私がそれを可能な限り渡すとき、私のために失敗していますstd::time_t。次のテストを参照してください。

std::cout   << "sizeof(std::time_t): " << sizeof(std::time_t) << '\n'
            << "sizeof(long long): " << sizeof(long long) << '\n'
            << "sizeof(unsigned int): " << sizeof(unsigned int) << "\n\n";

auto testgmtime = [](std::time_t time)
{
    std::tm* ptm = std::gmtime(&time);
    std::cout << (ptm ? "succeeded\n" : "failed\n");
};

testgmtime(std::numeric_limits<std::time_t>::max());
testgmtime(std::numeric_limits<long long>::max());
testgmtime(std::numeric_limits<long long>::max()-1);
testgmtime(static_cast<std::time_t>(std::numeric_limits<unsigned int>::max())*2);
testgmtime(std::numeric_limits<int>::max());

出力:

sizeof(std::time_t): 8
sizeof(long long): 8
sizeof(unsigned int): 4

failed
failed
failed
succeeded
succeeded

VS2012を使用しています。私が見ていない標準的な制限はありますか、それともこのVSはくだらないですか?どのような代替手段を使用できますか?

4

2 に答える 2

2

VS2012はくだらないことではありません。計算する。

time_tが 64 ビット整数の場合、その最大秒数は、符号なし整数の場合は 2 64 -1、符号付き整数の場合は 2 63 -1 です。

おおよそ、2 63秒は 2 63 /(60*60*24*365) ≈ 2.9*10 11年に相当します。

time_ttm_yearは 32 ビットのintで、その最大値は 2 31 -1 ≈ 2.1*10 9です。

明らかに、~2.9*10 11を 32 ビットの符号付き整数に格納することはできません。そしてgmtime()、あなたがそれを求めたとき、当然のことながら失敗します。

非常に大きな値を処理するためにgmtime()この回答の実装を変更できる場合があります。のオーバーフローを回避し、一部を およびにSecondsSinceEpoch + 11644473600ULL変更する必要があります。intsuintsuint64s

于 2012-07-15T08:35:17.747 に答える
1

gmtimeC++ は、それが失敗する可能性があるとだけ言っています。gmtime大量の入力に対するの動作を指定する標準はPOSIXです。

エラーが検出された場合、gmtime() は null ポインタを返し、エラーを示すために errno を設定します。

エラー

gmtime() および gmtime_r() 関数は、次の場合に失敗します。

[EOVERFLOW] 結果を表すことができません。

エポック以降の秒数が負の場合、実際の時間との関係はundefinedであるとは言えますが、制限が何であるかは直接述べていません。

別の方法として、ブーストを試してください

auto testgmtime = [](std::time_t time)
{
    std::cout << boost::posix_time::from_time_t(time) << '\n';
};

(ただし、私の Linux セットアップでは、from_time_t() は gmtime よりも早く上限に達するように見えます)

于 2012-07-15T07:16:57.400 に答える