てっきり切り捨てだと思っていて、それを想定した作りにしていたらハマったという話。
次のコードを見てください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| - - ! | - ! | - ! | - ! | - ! | | ! |
|
何をやっているかはコメントで記している通りです。
上記のコードを実行すると、 Visual C++ 2013 、 gcc 4.9.1 、 clang 3.5.0 では例えば次のように出力されます。
1424458932 1424458932
しかし Visual C++ 2012 では実行結果が異なり、例えば次のように出力されます。
1424459283 1424459284
500ミリ秒加算後の time_t
値が 1 増えています。
std::time_t
型の数値が何を表すかはコンパイラ依存ですが、VC++、gcc、clangといった主要コンパイラはEpoch*1からの経過秒数を表しています。
よって std::chrono::system_clock::to_time_t
関数では秒未満を何らかの方法で捨てることになります。
一番単純な実装としては秒未満切り捨てであり、VC++2013等の主要コンパイラはそうなっています。
前述のコードの 500 を 999 に変えても time_t
値は増加しません。
しかしVC++2012は最も近い秒数値に丸める実装になっています。
つまり秒未満が500ミリ秒以上であれば、変換元の time_point
値よりも未来の時刻を返してきます。
VC++2012でも、前述のコードの 500 を 499 に変えれば time_t
値は増加しなくなります。
関数の仕様としては「引数に渡した time_point
値と同等の time_t
値を返す」としか定義されていないはずなのでVC++2012の実装でも誤りではないと思いますが、注意する必要はあるでしょう。