現在の日付や時刻を得る

最近のgnuplotは日付や時刻の情報を取得する関数time()を持っていますので、簡単にこれらの情報を取得して使うことができます。また、時刻を文字列に変換する関数strftime()関数も便利です。少し古いバージョンのgnuplotの場合はこれらの関数がありませんが、代替策としてWindowsコマンドを介して時刻等を取得する方法があります。

(2015/2/1: 以下で、日本とGMTとの時差を8時間と間違えて記述していたので、9時間に修正しました。N君、指摘どうもありがとうございます。)

time()関数の使い方

日付や時刻の情報を取得するには、time()関数を使います。この関数には幾つかの使い方があります。

数値を引数にとる場合

まず、適当な数を引数に与えると、この関数は2000年1月1日からの経過時間を秒の単位で返します。時間はグリニッジ標準時(GMT)で計算されます。ここで、引数が整数の場合は帰ってくる値も整数値になり、引数が実数の場合は実数値になります。例えば、以下のようなスクリプトを実行してみましょう。

print time(0)
print time(0.0)

plot x     #グラフウィンドウの表示用

すると、gnuplotのコマンドラインには以下のように表示されます。確かに、整数の引数0を与えた場合は整数値が、実数の引数0.0を与えた場合は実数値が返ってきていることが分かります。

464459304
464459304.127394

文字数を引数にとる場合

文字数を引数に取った場合、time()関数は現在の時刻を文字列で指定されたフォーマットに直して文字列として返します。ただし、この時刻も、グリニッジ標準時での時刻です。例えば、以下のようなスクリプトを実行してみましょう。

print time("%Y/%m/%d %H:%M:%S")
plot x  #ウィンドウ表示用

すると、コマンドラインには例えば以下のように表示されます。

2014/09/19 16:41:18

この例からわかるように、引数の中の%Yは西暦年(4桁)、%mは月、%dは日、%Hは24時間表示の時、%Mは分、%Sは秒をそれぞれ出力することを意味します。ほかにも様々なフォーマット文字列がありますが、それらに関してはhelp timeを参照して下さい。

さて、上記コマンドで出てくる時刻はグリニッジ標準時ですので、日本の時刻より9時間遅れてしまっていることに注意して下さい。従って、上記の例は日本ではあまり使い道がありません。

strftime()関数と併用する

上述の時差の問題を解決するには、time()関数をstrftime()関数と併用する必要があります。strftime()関数は文字列引数と、数値の引数の二つを取ります。文字列引数は前述のtime()関数で使うのと同様の数値のフォーマット文字列、数値の引数は2000年1月1日からの経過時間(秒)です。そして、時間をフォーマット文字列で変換した結果を文字列として返します。つまり、time("...")strftime("...", time(0.0))と同じ結果を返します。しかし、strftime()を使う場合は2つ目の引数に適当な演算を行うことができますので、9時間の時差に対応する秒数9*3600を2つ目の引数に足してやれば、日本の時刻に対応した文字列を得ることができます。

実際に、以下の例を試してみましょう。

print "GMT: ", time("%Y/%m/%d %H:%M:%S")
print "JST: ", strftime("%Y/%m/%d %H:%M:%S", time(0)+9*3600)

plot x #ウィンドウ表示用

すると、以下のように、strftime()を使った方は確かにtime()関数の場合より9時間進んでおり、キチンと日本の時刻を表示していることが分かります。

GMT: 2015/01/31 13:22:05
JST: 2015/01/31 22:22:05

time()関数の応用例1: 時刻情報をラベルやファイル名に使う

時刻情報が取得できれば、グラフのラベルや、ファイル名などに用いることができます。

例えば、以下のようなスクリプトで、グラフのタイトルに、現在時刻を表示できます。

set title strftime("Plotted at %Y/%m/%d %H:%M:%S", time(0)+9*3600)
plot sin(x)

また、以下のようにすると、日付や時刻に応じた出力ファイルを生成できます。

set term post
set out strftime("data_%Y%m%d.eps", time(0)+9*3600)
plot sin(x)
set term pop
set out

これを実行すると、日付に応じて例えばdata_20140920.epsのような名前のファイルを生成することができます。

time()関数の応用例2: 時計を作る

以下のようなスクリプトを実行すると、時計を作ることができます。

if (exist("loop") == 0){
  set angles degrees
  set border 0
  unset xtics
  unset ytics
  set size ratio -1
  set xrange [-1:1]
  set yrange [-1:1]
  aconv(deg) = -deg + 90 # 角度を12時位置からの角度に変換する
  Lh = 0.4   # 短針の長さ
  Lm = 0.9   # 長針の長さ
  Ls = 0.95  # 秒針の長さ
  od = 1     # 時計の外半径
  id = 0.8   # 時計の内半径
  set for [i=1:12] arrow i from first id*cos(i*30),id*sin(i*30) to first od*cos(i*30),od*sin(i*30) lw 2 nohead
  set style fill solid border rgb "black"
  set object 1 circle at 0,0 size od fc rgb "yellow" fs solid lw 2
  }


time0 = time(0.0)+9*3600
hour = strftime("%H", time0)
min  = strftime("%M", time0)
sec  = strftime("%S", time0) + ( time0 - floor(time0) )


set arrow 100 from first 0,0 to Ls*cos(aconv(sec*6)),Lm*sin(aconv(sec*6)) lw 3 lc rgb "cyan" nohead 
set arrow 101 from first 0,0 to Lh*cos(aconv(hour*30)),Lm*sin(aconv(hour*30)) lw 9 lc rgb "dark-blue" nohead 
set arrow 102 from first 0,0 to Lm*cos(aconv(min*6)),Lm*sin(aconv(min*6)) lw 5 lc rgb "blue" nohead 

set label 1 at first 0,-0.3 center strftime("%b %d, %Y (%a) %H:%M:%S", time0)

plot 1/0 notitle

pause 0.05
reread

実行すると、以下のような時計が表示され、実際に動いていきます。(マシンパワーを食うだけで実用性はないですが…)

time()関数の応用例3: 処理時間の計測

time()関数で得た秒数の差を取れば、処理時間を計算できます。例えば、以下のようなスクリプトを考えてみましょう。

time0 = time(0.0)

set samples 100
plot sin(x)
print "required time (100 samples) = ", time(0.0)-time0, " sec"

time0 = time(0.0)

set samples 1000
plot sin(x)
print "required time (1000 samples) = ", time(0.0)-time0, " sec"

time0 = time(0.0)

set samples 10000
plot sin(x)
print "required time (10000 samples) = ", time(0.0)-time0, " sec"

time0 = time(0.0)

set samples 100000
plot sin(x)
print "required time (100000 samples) = ", time(0.0)-time0, " sec"

これはset samplesのパラメータが100の時、1000のとき、10000のとき、100000のときのそれぞれのsin(x)の表示にかかる時間を計測するためのスクリプトです。それぞれの表示前に、時刻をtime0という変数に保存しておき、表示完了後の時刻との差を取ることで、表示に要した時間を計算します。

私のパソコンでの実行結果は以下のようになりました。このように、確かにサンプル数が増えると所要時間が長くなっています。(100サンプルのときの表示時間が長いのは、ターミナルの初期化のせいだと思われます)

required time (100 samples) = 0.0180009603500366 sec
required time (1000 samples) = 0.0160010457038879 sec
required time (10000 samples) = 0.104005992412567 sec
required time (100000 samples) = 0.452026009559631 sec

日付や時刻を取得する(Windowsコマンドを使う)

古いgnuplotには現在の日付や時刻を得るための関数は用意されていません。しかしながら、以下のようにWindowsなどのコマンドを使うことで現在の日付や時刻を得ることができます。

まず、Windowsで現在の日付を文字列として取得するには以下のようにします。

tmpfile="time.plt"
system("echo date = \"%date%\" > ". tmpfile)
load tmpfile

この例では、2行目でecho date = \"%date%\" > time.pltというバッチコマンドを実行しています。これは、dateというWindowsの環境変数に入っている内容(%date%)とdate = \"および\"という文字列を連結して表示(echo)するという命令なのですが、> time.pltの部分で本来表示されるべき内容をファイルtime.pltに保存させています。これによって生成されるファイルtime.pltの中身は以下のようになっています。

date = "2010/01/20"

最後にこのtime.pltloadすることでgnuplot内のdateという変数に文字列2010/01/20が格納されたわけです。

さらに、以下のように部分文字列を取り出す関数substr()を使うと、年・月・日をそれぞれ取り出すことができます。

year  = substr(date, 1,4)
month = substr(date, 6,7)
day   = substr(date, 9,10)

なお、このように数字だけの文字列にしてしまえば、文字列を数値のようにも扱えます。例えば以下のようなことが可能です。

tomorrow = day + 1

これまでの内容の応用編として、例えばプロットした内容を日付のついたファイル名のEPSファイルに保存したい場合は以下のようにします。

tmpfile="time.plt"
system("echo date = \"%date%\" > ". tmpfile)
load tmpfile

year  = substr(date, 1,4)
month = substr(date, 6,7)
day   = substr(date, 9,10)

set title "year:" . year. " month: " . month . " day: " . day
plot sin(x)

set out "plot". year. month . day .".eps"
set term post eps color 
replot
set out
set term pop

上の例の青字で示した部分で、文字列連結演算子.を用いて文字列を連結しています。つまり、今日が2010年12月11日だとしたらplot20101211.epsという文字列を作っています。それをset outコマンドに与えて出力ファイル名に設定しています。

これを実行すると、以下のようなEPSファイルができます。

なお、最後のファイル名の設定の部分では、便利な文字列関数で紹介したstrsubst()関数を定義しておけば以下のようにしてもOKです。

set out "plot" . strsubst(date, "/", "") . ".eps"

同様に、時刻を取得するには以下のようにします。

tmpfile="time.plt"
system("echo time = \"%time%\" > ". tmpfile)
load tmpfile

原理は日付の取得と全く一緒です。

例えば以下のようにすると、グラフのタイトルに現在時刻を挿入できます。

tmpfile="time.plt"
system("echo time = \"%time%\" > ". tmpfile)
load tmpfile

set title time
plot sin(x)

時間・分・秒を分けて取得するには、さらに以下を付け加えます。

hour   = substr(time, 1,2)
minute = substr(time, 4,5)
second = substr(time, 7,11)

また、これらの文字列は数値としても扱えるので、例えば以下のように一日が始まってからの秒数を計算することもできます。

sec_from_midnight = hour*3600+minute*60+second