29
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

time.Timeから日付だけを取り出す

Posted at

現在時刻から日付だけを取り出す(今日の0:00)を作りたい時の話です。

Truncate()を使う

Time型にはTruncateメソッドが用意されていて、指定した大きさ以下の時刻を切り捨ててくれます。

func (t Time) Truncate(d Duration) Time
Truncate returns the result of rounding t down to a multiple of d (since the zero time). If d <= 0, Truncate returns t unchanged.

これに1日(24時間)を指定すれば簡単に日付を取り出せる気がします。

truncate1.go
package main

import (
        "time"
)

func main() {
        t, _ := time.Parse( time.ANSIC, "Fri Feb 7 13:58:00 2014" )
        println(t.Truncate( 24 * time.Hour ).Format(time.ANSIC))
}
output(truncate1.go)
Fri Feb  7 00:00:00 2014

上手く行っているように見えますが、これはあまりおすすめしません。なぜなら、

truncate2.go
package main

import (
        "time"
)

func main() {
        t := time.Now()
        println(t.Truncate( 24 * time.Hour ).Format(time.ANSIC))
}
output(truncate1.go)
Fri Feb  7 09:00:00 2014

こんな感じでタイムゾーンがUTCで無い時は時差分が残ってしまうからです。(Now()はLocationとして"Local"、Linuxの場合は/etc/localtimeを持ちます。Parse()はUTCになります。)
他のメソッドと違い、Truncateはタイムゾーンを考慮してくれないんですね。これは実装のdiv()あたりを読むとそんな感じになっていることがわかります。

Add()を併用する

そんな訳で、こんな感じにしないと上手く行きません。

truncate3.go
package main

import (
        "time"
)

func main() {
        t := time.Now()
        t = t.Truncate( time.Hour ).Add( - time.Duration(t.Hour()) * time.Hour )
        println(t.Format(time.ANSIC))
}

Hourはタイムゾーンを意識した値が帰るので、これを併用すれば意図通りに時刻を切り捨てることが出来ます。

Timeはタイムゾーンとあわせて抽象化したオブジェクトだと理解しているので、出来ればTruncateもUNIXタイムで単純に計算するのではなくてタイムゾーンを意識して動いて欲しい気もします。個人的には。

29
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?