123
timex/time.go
Normal file
123
timex/time.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package timex
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// IsAmericaSummerTime 是否为美国夏令时间
|
||||
// 夏令时开始于每年3月的第二个周日凌晨,人们需要将时间调早 (顺时针) 1个小时;
|
||||
// 夏令时结束于每年11月的第一个周日凌晨,人们需要将时间调晚 (逆时针) 1个小时。
|
||||
func IsAmericaSummerTime(t time.Time) (yes bool) {
|
||||
if t.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
month := t.Month()
|
||||
switch month {
|
||||
case 4, 5, 6, 7, 8, 9, 10:
|
||||
yes = true
|
||||
case 3, 11:
|
||||
day := t.Day()
|
||||
t1 := t.AddDate(0, 0, -day+1)
|
||||
weekday := int(t1.Weekday())
|
||||
if (month == 3 && day >= t1.AddDate(0, 0, 14-weekday).Day()) ||
|
||||
(month == 11 && day < t1.AddDate(0, 0, 7-weekday).Day()) {
|
||||
yes = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ChineseTimeLocation Return chinese time location
|
||||
func ChineseTimeLocation() *time.Location {
|
||||
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
loc = time.FixedZone("CST", 8*3600)
|
||||
}
|
||||
return loc
|
||||
}
|
||||
|
||||
func Between(t, begin, end time.Time) bool {
|
||||
return (t.After(begin) && t.Before(end)) || t.Equal(begin) || t.Equal(end)
|
||||
}
|
||||
|
||||
func DayStart(t time.Time) time.Time {
|
||||
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
|
||||
}
|
||||
|
||||
func DayEnd(t time.Time) time.Time {
|
||||
return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, time.Local)
|
||||
}
|
||||
|
||||
func MonthStart(t time.Time) time.Time {
|
||||
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local)
|
||||
}
|
||||
|
||||
func MonthEnd(t time.Time) time.Time {
|
||||
return DayEnd(MonthStart(t).AddDate(0, 1, -1))
|
||||
}
|
||||
|
||||
// IsAM Check is AM
|
||||
func IsAM(t time.Time) bool {
|
||||
return t.Hour() <= 11
|
||||
}
|
||||
|
||||
// IsPM Check is PM
|
||||
func IsPM(t time.Time) bool {
|
||||
return t.Hour() >= 12
|
||||
}
|
||||
|
||||
func WeekStart(yearWeek int) time.Time {
|
||||
year := yearWeek / 100
|
||||
week := yearWeek % year
|
||||
// Start from the middle of the year:
|
||||
t := time.Date(year, 7, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
// Roll back to Monday:
|
||||
if wd := t.Weekday(); wd == time.Sunday {
|
||||
t = t.AddDate(0, 0, -6)
|
||||
} else {
|
||||
t = t.AddDate(0, 0, -int(wd)+1)
|
||||
}
|
||||
|
||||
// Difference in weeks:
|
||||
_, w := t.ISOWeek()
|
||||
t = t.AddDate(0, 0, (week-w)*7)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func WeekEnd(yearWeek int) time.Time {
|
||||
t := WeekStart(yearWeek).AddDate(0, 0, 6)
|
||||
return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, time.UTC)
|
||||
}
|
||||
|
||||
func YearWeeksByWeek(startYearWeek, endYearWeek int) []int {
|
||||
weeks := make([]int, 0)
|
||||
weekStart := WeekStart(startYearWeek)
|
||||
weekEnd := WeekStart(endYearWeek)
|
||||
for {
|
||||
if weekStart.After(weekEnd) {
|
||||
break
|
||||
}
|
||||
y, w := weekStart.ISOWeek()
|
||||
weeks = append(weeks, y*100+w)
|
||||
weekStart = weekStart.AddDate(0, 0, 7)
|
||||
}
|
||||
return weeks
|
||||
}
|
||||
|
||||
func YearWeeksByTime(startDate, endDate time.Time) []int {
|
||||
y1, w1 := startDate.ISOWeek()
|
||||
y2, w2 := endDate.ISOWeek()
|
||||
return YearWeeksByWeek(y1*100+w1, y2*100+w2)
|
||||
}
|
||||
|
||||
// XISOWeek 非 ISO 周,从周日开始算起作为一周的第一天
|
||||
func XISOWeek(t time.Time) (year, week int) {
|
||||
t1 := time.Date(t.Year(), t.Month(), t.Day()+4-int(t.Weekday()), 0, 0, 0, 0, time.UTC)
|
||||
startTime := time.Date(t1.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
week = int(math.Ceil((float64((t1.Unix()-startTime.Unix())/86400) + 1) / 7))
|
||||
return startTime.Year(), week
|
||||
}
|
||||
217
timex/time_test.go
Normal file
217
timex/time_test.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package timex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIsAmericaSummerTime(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Date string
|
||||
SummerTime bool
|
||||
}{
|
||||
{"0001-01-01", false},
|
||||
{"2021-11-10", false},
|
||||
{"2021-12-10", false},
|
||||
{"2021-03-10", false},
|
||||
{"2021-03-14", true},
|
||||
{"2021-11-01", true},
|
||||
{"2021-10-10", true},
|
||||
{"2021-10-11", true},
|
||||
{"2021-10-12", true},
|
||||
{"2021-12-12", false},
|
||||
{"2022-03-15", true},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
d, _ := time.Parse("2006-01-02", testCase.Date)
|
||||
v := IsAmericaSummerTime(d)
|
||||
if v != testCase.SummerTime {
|
||||
t.Errorf("%s except %v, actual %v", testCase.Date, testCase.SummerTime, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBetween(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
t string
|
||||
begin string
|
||||
end string
|
||||
expected bool
|
||||
}{
|
||||
{"t1", "2022-01-01", "2022-01-01", "2022-01-01", true},
|
||||
{"t2", "2022-01-02", "2022-01-01", "2022-01-01", false},
|
||||
{"t3", "2022-01-02", "2022-01-01", "2022-01-02", true},
|
||||
}
|
||||
layout := "2006-01-02"
|
||||
for _, testCase := range testCases {
|
||||
tv, _ := time.Parse(layout, testCase.t)
|
||||
begin, _ := time.Parse(layout, testCase.begin)
|
||||
end, _ := time.Parse(layout, testCase.end)
|
||||
v := Between(tv, begin, end)
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDayStart(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
time string
|
||||
layout string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "2022-01-01T12:12:00.924Z", "2006-01-02T15:04:05Z", "2022-01-01 00:00:00"},
|
||||
{"t2", "2022-01-01 00:00:00", "2006-01-02 15:04:05", "2022-01-01 00:00:00"},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
tv, err := time.Parse(testCase.layout, testCase.time)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
v := DayStart(tv).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDayEnd(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
time string
|
||||
layout string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "2022-01-01 12:12:00", "2006-01-02 15:04:05", "2022-01-01 23:59:59"},
|
||||
{"t2", "2022-01-01 00:00:00", "2006-01-02 15:04:05", "2022-01-01 23:59:59"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
tv, _ := time.Parse(testCase.layout, testCase.time)
|
||||
v := DayEnd(tv).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthStart(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
time string
|
||||
layout string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "2022-01-12 12:12:00", "2006-01-02 15:04:05", "2022-01-01 00:00:00"},
|
||||
{"t2", "2022-01-21 00:00:00", "2006-01-02 15:04:05", "2022-01-01 00:00:00"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
tv, _ := time.Parse(testCase.layout, testCase.time)
|
||||
v := MonthStart(tv).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthEnd(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
time string
|
||||
layout string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "2022-01-12 12:12:00", "2006-01-02 15:04:05", "2022-01-31 23:59:59"},
|
||||
{"t2", "2022-02-21 00:00:00", "2006-01-02 15:04:05", "2022-02-28 23:59:59"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
tv, _ := time.Parse(testCase.layout, testCase.time)
|
||||
v := MonthEnd(tv).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeekStart(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
yearWeek int
|
||||
expected string
|
||||
}{
|
||||
{"t1", 202201, "2022-01-03 00:00:00"},
|
||||
{"t2", 202202, "2022-01-10 00:00:00"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
v := WeekStart(testCase.yearWeek).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeekEnd(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
yearWeek int
|
||||
expected string
|
||||
}{
|
||||
{"t1", 202201, "2022-01-09 23:59:59"},
|
||||
{"t2", 202202, "2022-01-16 23:59:59"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
v := WeekEnd(testCase.yearWeek).Format("2006-01-02 15:04:05")
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYearWeeksByWeek(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
beginYearWeek int
|
||||
endYearWeek int
|
||||
expected []int
|
||||
}{
|
||||
{"t1", 202201, 202202, []int{202201, 202202}},
|
||||
{"t2", 202201, 202204, []int{202201, 202202, 202203, 202204}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
v := YearWeeksByWeek(testCase.beginYearWeek, testCase.endYearWeek)
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYearWeeksByTime(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
beginDate string
|
||||
endDate string
|
||||
expected []int
|
||||
}{
|
||||
{"t1", "2022-01-01", "2022-01-02", []int{202152}},
|
||||
{"t2", "2022-01-01", "2022-02-02", []int{202152, 202201, 202202, 202203, 202204, 202205}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
beginDate, _ := time.Parse("2006-01-02", testCase.beginDate)
|
||||
endDate, _ := time.Parse("2006-01-02", testCase.endDate)
|
||||
v := YearWeeksByTime(beginDate, endDate)
|
||||
assert.Equal(t, testCase.expected, v, testCase.tag)
|
||||
}
|
||||
}
|
||||
|
||||
// https://savvytime.com/week-number
|
||||
func TestXISOWeek(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
date string
|
||||
expected string
|
||||
}{
|
||||
{"t1", "2022-01-01", "202152"},
|
||||
{"t2", "2022-01-02", "202201"},
|
||||
{"t3", "2022-01-09", "202202"},
|
||||
{"t4", "2022-01-10", "202202"},
|
||||
{"t5", "2022-01-15", "202202"},
|
||||
{"t6", "2022-01-16", "202203"},
|
||||
{"t7", "2022-01-17", "202203"},
|
||||
{"t8", "2022-01-29", "202204"},
|
||||
{"t9", "2022-12-25", "202252"},
|
||||
{"t10", "2023-01-01", "202301"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
d, _ := time.Parse("2006-01-02", testCase.date)
|
||||
year, week := XISOWeek(d)
|
||||
assert.Equal(t, testCase.expected, fmt.Sprintf("%d%02d", year, week), testCase.tag)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user