因为有个业务需要算周别,且是按照周天到周六的算法,和常见的周一到周天,有些区别,所以ISOWeek函数就不好使了,找了下发现Go没有现成的,也没人实现过,所以就有了这篇文章。

直接上代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
type timex struct {
time.Time
}

func newDate(year int, month time.Month, day int, hour int, min int, sec int, nsec int, loc *time.Location) timex {
return timex{time.Date(year, month, day, hour, min, sec, nsec, loc)}
}

// ISO Week 周一到周天
func (tx timex) whichWeek() int {
//tx := time.Now()

// https://weeknumber.com/?q=02%2F01%2F2022

// Thursday in current week decides the year.
tm1 := time.Date(tx.Year(), tx.Month(), tx.Day()+3-(int(tx.Weekday())+6)%7, 0, 0, 0, 0, time.UTC)
// January 4 is always in week 1.
week1 := time.Date(tm1.Year(), 1, 4, 0, 0, 0, 0, time.UTC)
// Adjust to Thursday in week 1 and count number of weeks from date to week1.
abs := 1 + math.Round((float64((tm1.Unix()-week1.Unix())/86400)-float64(3)+float64((int(week1.Weekday())+6)%7))/7)
return int(abs)
}

// 周天到周六
func (tx timex) whichWeek2() int {

tm1 := time.Date(tx.Year(), tx.Month(), tx.Day()+4-int(tx.Weekday()), 0, 0, 0, 0, time.UTC)
yearStart := time.Date(tm1.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
sd := math.Ceil((float64((tm1.Unix()-yearStart.Unix())/86400) + 1) / 7)

return int(sd)
}

// 计算周开始的起始时间
func (tx timex) WeekStart(year, week int) time.Time {
if year == 0 || week == 0 {
year = tx.Year()
week = int(tx.Weekday())
}

// Start from the middle of the year:
t2 := newDate(year, 7, 1, 0, 0, 0, 0, time.UTC)

// Roll back to Monday:
if wd := t2.Weekday(); wd != time.Sunday {
t2.Time = t2.AddDate(0, 0, -int(wd))
}

// Difference in weeks:
w := t2.whichWeek2()
t2.Time = t2.AddDate(0, 0, (week-w)*7)

if wd := t2.Weekday(); wd != time.Sunday {
t2.Time = t2.AddDate(0, 0, -6)
}

return t2.Time
}

// 计算ISO周别的起始时间
func WeekStart(year, week int) time.Time {
// 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)

if wd := t.Weekday(); wd != time.Sunday {
t = t.AddDate(0, 0, -6)
} else {
t = t.AddDate(0, 0, -int(wd)+1)
}

return t
}

参考链接:

https://stackoverflow.com/questions/52300644/date-range-by-week-number-golang

https://stackoverflow.com/questions/45910292/get-week-number-with-week-starting-from-sunday