Go言語で時刻を¶
来たるべきGoConに向けていろいろ調査。やっぱり事前準備が重要ですよね。
go-modeのインストール¶
エディタはもちろんemacsですが、さすがにgo-modeは標準で入っていないので入れます。
melpaを追加
(require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t) (add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/")) (package-initialize)
M-x list-package
go-modeを探してiでインストールの印をつけてxでインストール
これだけで準備OKです。
さて、言語の勉強は localtimeからはじめる のが流行りなのでgoの時刻関係ライブラリであるtime packageを調べてみます。
time packageを使ってみる¶
http://golang.org/pkg/time/ にドキュメントがあります。
適当なディレクトリを掘って、 main.go というファイルを作り、以下のよ うに書きます。
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now() // 現在時刻を得る
fmt.Println(t) // 表示
}
pygmentsはgoにも対応しているのが素敵ですね。 あとは go run で実行です。
% go run main.go
2013-04-09 22:57:14.831084 +0900 JST
%
goはコンパイルする言語ですが、go runで実行することで、スクリプト言語の ように逐次コンパイルして実行してくれます。
さて、現在時刻も得られたので、もう少しいろいろしてみます。
時刻の一部を取得¶
fmt.Println(t.Day())
fmt.Println(t.ISOWeek())
fmt.Println(t.Unix())
fmt.Println(t.Location())
fmt.Println(t.MarshalJSON())
/* 結果
9
2013 15
1365548234
UTC
[34 50 48 49 51 45 48 52 45 48 57 84 50 50 58 53 55 58 49 52 90 34] <nil>
*/
簡単ですね。
文字列から時刻へ¶
指定の文字列を指定のフォーマットに従って認識して時刻に直します。pythonでいうと、 datetime.strptime ですね。
var timeformat = "2006-01-02 15:04:05"
t,err := time.Parse(timeformat, "2013-04-09 22:57:14")
if err != nil{
panic(err)
}
(追記: 初出時timeformatが一部間違っていました。コメントでの指摘ありがとうございます)
ここで注目なのはtimeformatです。goでは、pythonやperlなどのようなdateコ マンドの%Yとかは使いません。
Mon Jan 2 15:04:05 MST 2006 (MST is GMT-0700)
という文字列からそれぞれの要素を取ってformatとします。
例をいくつか出します。
- "%Y%M%dT%H%m%s"の場合、
var timeformat = "20060102T150405" を使う
- "%H%m%s %Y/%M/%d "とかが仮にあった場合
var timeformat = "150405 2006/01/02" を使う
つまり、timeformatだからといって好き勝手な文字列を使うのではなく、上記 の文字列から選んでね、ということです。
一見%Yとかの方がいい気もしますが、あれ言語によって微妙に違ったり、%mと %Mがごっちゃになったりするしで、この方がわかりやすいと思います。
時刻から文字列へ¶
fmt.Println()でいい感じにISO-8601にのっとって出力してくれますが、もう少し変えたい場合もあります。pythonでいうと、 datetime.strftime です。
fmt.Println(t.Format("20060102 150405"))
// 結果
// 20130409 225714
Format()を使います。この形式もParseと同じですね。
未来か判定¶
2つのTime型を比べて未来かどうかを判定します。
t, err := time.Parse(timeformat, "2013-04-09 22:57:14")
f, err := time.Parse(timeformat, "2012-01-01 22:57:14")
fmt.Println(f.After(t))
// -> false
After()を使います。あるいはBefore()を使ってもいいですね。
時刻の差分¶
pythonでいうと、 datetime.timedelta ですね。
t, err := time.Parse(timeformat, "2013-04-09 22:57:14")
f, err := time.Parse(timeformat, "2012-01-01 22:57:14")
fmt.Println(f.Sub(t))
// -> -11136h0m0s
Sub()の返り値はDuration型となります。Duration型は時間までなようですね。
一日後、一日前¶
AddDate()を使います。もちろん、負の値も対応です。
var timeformat = "2006-01-02 15:04:05"
f, err := time.Parse(timeformat, "2012-12-31 00:00:00")
if err != nil {
panic(err)
}
fmt.Println(f.AddDate(0, 0, 1))
// -> 2013-01-01 00:00:00 +0000 UTC
// 日が足りない場合は足される
t, err := time.Parse(timeformat, "2013-01-31 00:00:00")
fmt.Println(t.AddDate(0, 1, 0))
// -> 2013-03-03 00:00:00 +0000 UTC
// うるう年も対応
t2, err := time.Parse(timeformat, "2012-03-01 00:00:00")
fmt.Println(t2.AddDate(0, 0, -1))
// -> 2012-02-29 00:00:00 +0000 UTC
t3, err := time.Parse(timeformat, "2012-02-29 00:00:00")
fmt.Println(t3.AddDate(1, 0, 0))
// -> 2013-03-01 00:00:00 +0000 UTC
Sleep¶
ここまでは時刻関連でしたが、timeパッケージはsleepなどもできます。
time.Sleep(100 * time.Millisecond)
タイムアウト¶
After()を使うことで指定した時間後にchannelを通じてメッセージが送られてきます。Erlangみたいですね。
c1 := make(chan string)
select {
case msg1 := <- c1:
fmt.Println("Message 1", msg1)
case <- time.After(time.Second):
fmt.Println("timeout")
}
一定間隔で¶
Tickを使うことで、指定した時間の間隔でメッセージが送られてきます。
c := time.Tick(1 * time.Second)
for now := range c {
fmt.Printf("%v\n", now)
}
まとめ¶
go言語のtimeパッケージを使ってみました。時刻関係はいろいろハマりどころ があるですが、標準でここまで揃ってると使いやすいですね。
また、go言語の魅力であるchannelを使う例も示しました。channelと組み合わ せることでいろいろな広がりが出てきますね。(といっても、自分ではChannel を使いこなせてないんですが…)
Comments
comments powered by Disqus