D言語の時間の扱いがよくわからないのでメモ。
固定フレームレートのメインループを実装したかっただけなのだけど・・・
Time Points
時間軸の一点を指す。
4種類ある。
SysTime
hnsecs精度のSystemClock。Timezone付き
std.datetime.Clock.currTime();
現在時刻を取得するのはこれ。
https://dlang.org/phobos/std_datetime.html#.Clock.currTime
Date
日付。Timezone無し。
cast(std.datetime.Date)std.datetime.Clock.currTime
todayとか探していたら見つからなくて時間かかった。castだったとは。
TimeOfDay
00:00:00 - 23:59.59。Timezone無し
cast(std.datetime.TimeOfDay)std.datetime.Clock.currTime
DateTime
Date + TimeOfDay。Timezone無し
cast(std.datetime.DateTime)std.datetime.Clock.currTime
Duration
時間の長さの表現。
C#のTimeSpanにあたる。
dur関数で作れる。
std.datetime.dur!"hours"(17)
もしくはTimePointsの引き算で作れる。
std.datetime.TimeOfDay(17, 2)-std.datetime.TimeOfDay(16, 2)
特定の単位の数に変換するにはtotalを使う。
auto h=std.datetime.dur!"hours"(1);
auto m=h.total!"minutes";
writefln("%s: %s", typeid(m), m);
|| long: 60
以下の単位(unit)がある。
- years
- months
- weeks
- days
- hours
- minutes
- seconds
- msecs
- usecs
- hnsecs
- nsecs
Time Intervals
TimePointsを起点にした時間のレンジ。
Durationは単純に長さだが、Time Intervalは時間軸の範囲を指す。
あまり使わなさそうである。
DurationとSysTimeの精度は100nsec
C#のTimeSpanのTickとかと同じ。
64bitで100nsecを保持すると
29,000 B.C.から29,000 A.Dを表現できるらしい。
time_t
unix time.
auto t=std.datetime.Clock.currTime();
printWithType(t);
printWithType(t.toUnixTime);
auto s=std.datetime.unixTimeToStdTime(t.toUnixTime);
printWithType(std.datetime.SysTime(s));
|| std.datetime.SysTime: 2016-Oct-01 16:22:26.7489453
|| int: 1475306546 <- unix_time
|| std.datetime.SysTime: 2016-Oct-01 16:22:26
std.datetime.StopWatch
FPS待ちクラス
class FpsClock(int Target, int MarginMsecs = 5)
{
import std.datetime;
SysTime m_lastTime;
static immutable Duration frameDuration=dur!"msecs"(1000/Target - MarginMsecs);
this()
{
m_lastTime=Clock.currTime;
}
// loopの頭に呼ぶ
Duration newFrame()
{
auto now=Clock.currTime;
auto duration=now-m_lastTime;
m_lastTime=now;
return duration;
}
// loopの終わりで呼んで早すぎる場合にはsleepして待つ
void waitNextFrame()
{
import core.thread;
auto now=Clock.currTime;
auto delta=now-m_lastTime;
if(delta < frameDuration)
{
auto wait=frameDuration-delta;
Thread.sleep(wait);
}
}
}
Clock.currTimeで実装してみた。
StopWatchの方が精度がよかったりするのだろうか。
auto fps=new FpsClock!30
while(loop)
{
auto delta=fps.newFrame();
// rendering...
fps.waitNextFrame();
}
終わり
とりあえず
std.datetime.Clock.currTime
を押さえておけば他はドキュメントを見ればよい。