3
0

More than 3 years have passed since last update.

Golangでのtime packageのいろんな使い方まとめました

Last updated at Posted at 2020-03-09

概要

golangでtime objectを利用してあれこれデータを操作したりすることがあり、その時に調べたことややったことをまとめました。

目次

  • stringからtime.Timeへ変換
  • stringからtime.Timeへ変換(Timezoneを考慮)
  • time型objectのTimeZoneのみを変換する
  • 日付から特定のTimzoneの00:00:00を作る
  • 〇〇前、〇〇後の時刻を取得する
  • 2つの時刻を比較する (差分、Before、After、Since、Until)
  • 2つの時刻から間の日付リストを作る
  • 2つの時刻からその間の特定の曜日の日付リストを作る

stringからtime.Timeへ変換

string-to-time.go

dateLayout := "2006-01-02"
dateTimeLayout := "2006-01-02 15:04:05"
dateTarget := "2020-01-28"
dateTimeTarget := "2020-01-28 13:14:15"

dateObject, _ := time.Parse(dateLayout, dateTarget) // 2020-01-28 00:00:00 +0000 UTC
dateTimeObject, _ := time.Parse(dateTimeLayout, dateTimeTarget) // 2020-01-28 13:14:15 +0000 UTC

試したい方はこちら -> https://play.golang.org/p/o27qyHiuOob

ちなみに、time packageを使うにあたって、time.Formatやtime.Parseを使う際のLayoutは上記以外機能してくれませんので注意!
ちなみになぜこの並びかと言うと、 MST(米国山岳部標準時)になおすとあら不思議、綺麗な数字並びになっているからなんです。

Mon Jan 2 15:04:05 MST 2006
01/02 03:04:05PM '06 -0700

stringからtime.Timeへ変換(Timezoneを考慮)

Parse, ParseInLocationを使う

string-to-timeWithTimezone.go
// 日付だけの場合は、defaultでUTCの00:00:00になる
targetDate := "2020-03-09"
date, _ := time.Parse("2006-01-02", targetDate) // 2020-03-09 00:00:00 +0000 UTC

// 日付だけでTimeZoneを指定した場合は、指定したTimeZoneの00:00:00になる
targetTimezone := "Asia/Tokyo"
tzloc, _ := time.LoadLocation(targetTimezone)
dateWithTimezone, _ := time.ParseInLocation("2006-01-02", targetDate, tzloc) // 2020-03-09 00:00:00 +0900 JST

// 日時だけの場合(TimeZoneなし)は、defaultでUTCになる
targetDT := "2020-03-09T09:00:00"
dateTime, _ := time.Parse("2006-01-02 15:04:05", targetDT) // 2020-03-09 09:00:00 +0000 UTC

// 日時だけの場合(TimeZoneなし)でTimeZoneを指定した場合は、指定したTimeZoneが付加される
dateTimeSetTZ, _ := time.ParseInLocation("2006-01-02 15:04:05", targetDT, tzloc) // 2020-03-09 09:00:00 +0900 JST

// 日時とTimeZoneがある場合は、そのままtime型に変換されるだけ
targetDTWithTZ := "2020-03-09T09:00:00+05:00"
dateTimeWithTZ, _ := time.Parse(time.RFC3339, targetDTWithTZ) // 2020-03-09 09:00:00 +0500 +0500

// 日時とTimeZoneがある場合は、TimeZoneは変換されない!
// TimeZoneだけを変換したい場合はInを使おう。詳細は次のセクション
dateTimeWithTZSetTZ, _ := time.ParseInLocation(time.RFC3339, targetDTWithTZ, tzloc) // 2020-03-09 09:00:00 +0500 +0500

試したい方はこちら -> https://play.golang.org/p/cTIwh-vp2Q1

time型objectのTimeZoneのみを変換する

Inを使う

change-timezone.go
targetDT := "2020-03-09T09:00:00+05:00"
targetTZ := "Asia/Tokyo"
tzloc, _ := time.LoadLocation(targetTZ)

dt, _ := time.Parse(time.RFC3339, targetDT) // 2020-03-09 09:00:00 +0500 +0500
dtConvertTZ := dt.In(tzloc) // 2020-03-09 13:00:00 +0900 JST

試したい方はこちら -> https://play.golang.org/p/baSzGM4pftJ

日付から特定のTimzoneの00:00:00を作る

date-to-dateTimeMidnightWithTimezone.go
target := "2020-01-28"
targetTimezone := "Asia/Tokyo"
date, _ := time.Parse("2006-01-02", target) // 2020-01-28 00:00:00 +0000 UTC

tzloc, _ := time.LoadLocation(targetTimezone)

dateTimeMidnight := time.Date(date.Year(),
    date.Month(),
    date.Day(),
    0, 0, 0, 0, tzloc) // 2020-01-28 00:00:00 +0900 JST

試したい方はこちら -> https://play.golang.org/p/E7je0DSAqiW

〇〇前、〇〇後の時刻を取得する

AddまたはAddDateを使います。前か後かは正の数か負の数で表す。

increase-reduce-time.go
dtString := "2020-03-05T15:10:47+09:00"
dt, _ := time.Parse(time.RFC3339, dtString)
// 1分後
t1 := dt.Add(1 * time.Minute) // 2020-03-05 15:11:47 +0900 +0900
// 1時間後
t2 := dt.Add(1 * time.Hour) // 2020-03-05 16:10:47 +0900 +0900
// 1年2ヶ月3日後
t3 := dt.AddDate(1, 2, 3) // 2021-05-08 15:10:47 +0900 +0900

// 1分前
t4 := dt.Add(-1 * time.Minute) // 2020-03-05 15:09:47 +0900 +0900
// 1時間前
t5 := dt.Add(-1 * time.Hour) // 2020-03-05 14:10:47 +0900 +0900
// 1年2ヶ月3日前
t6 := dt.AddDate(-1, -2, -3) // 2019-01-02 15:10:47 +0900 +0900

試したい方はこちら -> https://play.golang.org/p/pZahLsfwesB

2つの時刻を比較する (差分、Before、After、Since、Until)

Sub, After, Before, Since, Untilを使う

time-comparizon.go
t1String := "2020-02-01T13:14:15+09:00"
t2String := "2020-02-10T13:14:15+09:00"
t1, _ := time.Parse(time.RFC3339, t1String)
t2, _ := time.Parse(time.RFC3339, t2String)
// t1 - t2
duration1 := t1.Sub(t2) // -216h0m0s
// (t2 - t1)を日数に計算する
duration2 := int(t2.Sub(t1).Hours()) / 24 // 9
// 今はt1からどれだけ経過しているか (time.Now().Sub(t1)と同じ. now - t1)
time.Since(t1)
// t1は今からどれだけ経過しているか (t1.Sub(time.Now())と同じ. t1 - now)
time.Until(t1)
// t1はt2より後か
t1.After(t2) // false
// t1はt2より前か
t1.Before(t2) // true

試したい方はこちら -> https://play.golang.org/p/zLshTmUKVyj

日時からその日の00:00:00を作る

dateTime-to-dateTimeMidnightWithTimezone.go
dateTimeTarget := "2020-01-28T13:14:15+09:00"
dateTime, _ := time.Parse(time.RFC3339, dateTimeTarget) // 2020-01-28 13:14:15 +0900 +0900

dateTimeMidnight := time.Date(dateTime.Year(),
    dateTime.Month(),
    dateTime.Day(),
    0, 0, 0, 0, dateTime.Location()) // 2020-01-28 00:00:00 +0900 +0900

試したい方はこちら -> https://play.golang.org/p/kzaf6x2gX4d

2つの時刻から間の日付リストを作る

fromString := "2020-02-01T13:14:15+09:00"
toString := "2020-02-05T13:14:15+09:00"
from, _ := time.Parse(time.RFC3339, fromString)
to, _ := time.Parse(time.RFC3339, toString)

dateDuration := int(to.Sub(from).Hours()) / 24 + 1 // 5

var dates []string
for i := 0; i < dateDuration; i++ {
    date := from.AddDate(0, 0, i).Format("2006-01-02")
    dates = append(dates, date)
}

// dates: [2020-02-01 2020-02-02 2020-02-03 2020-02-04 2020-02-05]

試したい方はこちら -> https://play.golang.org/p/sNcbcFET2KV

2つの時刻からその間の特定の曜日の日付リストを作る

dateList-dependingOf-dayOfWeek.go
fromString := "2020-02-01T13:14:15+09:00"
toString := "2020-02-10T13:14:15+09:00"
from, _ := time.Parse(time.RFC3339, fromString)
to, _ := time.Parse(time.RFC3339, toString)
targetDayOfWeek := []string{"Monday", "Tuesday", "Wednesday"}

dateDuration := int(to.Sub(from).Hours()) / 24 + 1 // 10

var dates []string
for i := 0; i < dateDuration; i++ {
    date := from.AddDate(0, 0, i)
    if isValidDayOfWeek(date, targetDayOfWeek) {
        dates = append(dates, date.Format("2006-01-02"))
    }
}

// dateの曜日が特定の曜日に含まれるかCheck
func isValidDayOfWeek(date time.Time, dayOfWeek []string) bool {
    for _, dow := range dayOfWeek {
        if date.Weekday() == getIntDayOfWeek(dow) {
            return true
        }
    }
    return false
}

// 英語の曜日(string)をWeekday型に変換
func getIntDayOfWeek(day string) time.Weekday {
    switch day {
    case "Sunday":
        return time.Sunday
    case "Monday":
        return time.Monday
    case "Tuesday":
        return time.Tuesday
    case "Wednesday":
        return time.Wednesday
    case "Thursday":
        return time.Thursday
    case "Friday":
        return time.Friday
    case "Saturday":
        return time.Saturday
    }
    return time.Saturday
}

// dates: [2020-02-03 2020-02-04 2020-02-05 2020-02-10] 

試したい方はこちら -> https://play.golang.org/p/y6AOBbp5hdG

3
0
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
3
0