概要
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へ変換
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を使う
// 日付だけの場合は、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を使う
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を作る
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を使います。前か後かは正の数か負の数で表す。
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を使う
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を作る
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つの時刻からその間の特定の曜日の日付リストを作る
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