type TRecurrenceInfo struct {
EventId uint64 `json:"-"`
Frequency string `json:"frequency,omitempty"`
Interval int64 `json:"interval,omitempty"`
ByDay string `json:"byday,omitempty"`
ByMonth string `json:"bymonth,omitempty"`
ByMonthDay string `json:"bymonthday,omitempty"`
BySetPos string `json:"bysetpos,omitempty"`
RecurrenceCount int64 `json:"repeatcount,omitempty"`
RecurrenceEndDate int64 `json:"repeatenddate,omitempty"`
type TRecurrenceInfoList []*TRecurrenceInfo
func (r *TRecurrenceInfo) EqualTo(rhs *TRecurrenceInfo) bool {
return r.Frequency == rhs.Frequency &&
r.Interval == rhs.Interval &&
r.ByMonth == rhs.ByMonth &&
r.ByMonthDay == rhs.ByMonthDay &&
r.BySetPos == rhs.BySetPos &&
r.RecurrenceCount == rhs.RecurrenceCount &&
r.RecurrenceEndDate == rhs.RecurrenceEndDate
DayDuration = int64(time.Hour) * 24
WeekDuration = int64(time.Hour) * 24 * 7
MonthDuration = int64(time.Hour) * 24 * 30
YearDuration = int64(time.Hour) * 24 * 365
func (rule *TRecurrenceInfo) GetRecurrenceTime(index, fstStartTime, fstEndTime int64, loc *time.Location) (start, end time.Time) {
var deltaDuration int64 = 0
if rule.RecurrenceCount > 0 {
if index >= rule.RecurrenceCount {
start = time.Unix(fstStartTime, 0).In(loc)
end = time.Unix(fstEndTime, 0).In(loc)
interval := rule.Interval
switch strings.ToUpper(rule.Frequency) {
case DayRecurrenceFrequency:
deltaDuration = index * interval * DayDuration
start = start.Add(time.Duration(deltaDuration))
end = end.Add(time.Duration(deltaDuration))
case WeekRecurrenceFrequency:
dayList := strings.Split(rule.ByDay, ",")
dayLen := int64(len(dayList))
dayList = append(dayList, rule.ByDay)
start, end = rule.GetWeekRuleFstDay(start, end, loc)
startWeekday := start.Weekday()
firstDay := string(WeekdayString(startWeekday))
firstDayInt := int64(startWeekday)
for i, day := range dayList {
indexForRule := index + int64(offset)
i := indexForRule / dayLen
j := indexForRule % dayLen
deltaDuration = i * interval * WeekDuration
dayInt := int64(WeekdayInt(dayList[j]))
delta := (dayInt - firstDayInt) * DayDuration
start = start.Add(time.Duration(deltaDuration))
end = end.Add(time.Duration(deltaDuration))
case MonthRecurrenceFrequency:
dayList := strings.Split(rule.ByMonthDay, ",")
dayLen := int64(len(dayList))
dayList = append(dayList, rule.ByMonthDay)
start, end = rule.GetMonthRuleFstDay(start, end, dayList, loc)
_, _, startMonthDay := start.Date()
for i, day := range dayList {
if ToInt64(day, 0) == int64(startMonthDay) {
indexForRule := index + int64(offset)
i := indexForRule / dayLen
j := indexForRule % dayLen
nextMonthTime := start.AddDate(0, int(i*interval), 0)
deltaDuration = int64(nextMonthTime.Sub(start))
dayInt := ToInt64(dayList[j], 0)
delta := (dayInt - int64(startMonthDay)) * DayDuration
start = start.Add(time.Duration(deltaDuration))
end = end.Add(time.Duration(deltaDuration))
bySetPos := ToInt64(rule.BySetPos, 1)
year, month, _ := start.Date()
hour, minute, sec := start.Clock()
start = Date(year, month+time.Month(index*interval), int(bySetPos),
WeekdayInt(rule.ByDay), hour, minute, sec, start.Location())
year, month, _ = end.Date()
hour, minute, sec = start.Clock()
end = Date(year, month+time.Month(index*interval), int(bySetPos),
WeekdayInt(rule.ByDay), hour, minute, sec, end.Location())
case YearRecurrenceFrequency:
nextYearTime := start.AddDate(int(index*interval), 0, 0)
deltaDuration = int64(nextYearTime.Sub(start))
start = start.Add(time.Duration(deltaDuration))
end = end.Add(time.Duration(deltaDuration))
bySetPos := ToInt64(rule.BySetPos, 1)
year, month, _ := start.Date()
hour, minute, sec := start.Clock()
start = Date(year+int(index*interval), month, int(bySetPos),
WeekdayInt(rule.ByDay), hour, minute, sec, start.Location())
year, month, _ = end.Date()
hour, minute, sec = end.Clock()
end = Date(year+int(index*interval), month, int(bySetPos),
WeekdayInt(rule.ByDay), hour, minute, sec, end.Location())
if rule.RecurrenceEndDate == 0 {
last := time.Unix(rule.RecurrenceEndDate, 0).In(start.Location())
func (rule *TRecurrenceInfo) convertDayList() []int {
dayList := strings.Split(rule.ByDay, ",")
dayList = append(dayList, rule.ByDay)
dayWeekInts := make([]int, 0)
for _, day := range dayList {
dayWeekInt := int(WeekdayInt(day))
dayWeekInts = append(dayWeekInts, dayWeekInt)
func (rule *TRecurrenceInfo) GetWeekRuleFstDay(start, end time.Time, loc *time.Location) (fstStartTime, fstEndTime time.Time) {
startWeekday := start.Weekday()
startWeekDayInt := int64(startWeekday)
dayList := rule.convertDayList()
for i, day := range dayList {
dayInt := ToInt64(day, 0)
if dayInt == startWeekDayInt {
if dayInt > startWeekDayInt {
fstWeekDay := int64(dayList[offset])
deleduration = (fstWeekDay - startWeekDayInt) * DayDuration
deleduration = (int64(7) - startWeekDayInt + fstWeekDay) * DayDuration
fstStartTime = start.Add(time.Duration(deleduration))
fstEndTime = end.Add(time.Duration(deleduration))
func (rule *TRecurrenceInfo) GetMonthRuleFstDay(start, end time.Time, dayList []string, loc *time.Location) (fstStartTime, fstEndTime time.Time) {
_, _, startMonthDay := start.Date()
for i, day := range dayList {
dayInt := ToInt64(day, 0)
if dayInt == int64(startMonthDay) {
if dayInt > int64(startMonthDay) {
dayInt := int(ToInt64(dayList[offset], 0))
year, month, _ := start.Date()
hour, minute, sec := start.Clock()
fstStartTime = time.Date(year, month, dayInt, hour, minute, sec, 0, loc)
year, month, _ = end.Date()
hour, minute, sec = end.Clock()
fstEndTime = time.Date(year, month, dayInt, hour, minute, sec, 0, loc)
func Date(year int, month time.Month, monthWeek int, weekDay time.Weekday, hour, minute, sec int, loc *time.Location) time.Time {
monthFstDayTime := time.Date(year, month, 1, hour, minute, sec, 0, loc)
week := monthFstDayTime.Weekday()
monthDay = 1 + int(time.Sunday) - int(week)
monthDay = monthDay + (monthWeek * 7) + int(weekDay)
return time.Date(year, month, monthDay, hour, minute, sec, 0, loc)
func ToInt64(v interface{}, defaultVal int64) int64 {
i, err := strconv.ParseInt(v.(string), 10, 64)
return int64(v.(float64))
type RecurrenceFrequency string
SecondRecurrenceFrequency RecurrenceFrequency = "SECONDLY"
MinuteRecurrenceFrequency = "MINUTELY"
HourRecurrenceFrequency = "HOURLY"
DayRecurrenceFrequency = "DAILY"
WeekRecurrenceFrequency = "WEEKLY"
MonthRecurrenceFrequency = "MONTHLY"
YearRecurrenceFrequency = "YEARLY"
type RecurrenceWeekday string
MondayRecurrenceWeekday RecurrenceWeekday = "MO"
TuesdayRecurrenceWeekday = "TU"
WednesdayRecurrenceWeekday = "WE"
ThursdayRecurrenceWeekday = "TH"
FridayRecurrenceWeekday = "FR"
SaturdayRecurrenceWeekday = "SA"
SundayRecurrenceWeekday = "SU"
func WeekdayString(weekday time.Weekday) RecurrenceWeekday {
r = SundayRecurrenceWeekday
r = MondayRecurrenceWeekday
r = TuesdayRecurrenceWeekday
r = WednesdayRecurrenceWeekday
r = ThursdayRecurrenceWeekday
r = FridayRecurrenceWeekday
return SaturdayRecurrenceWeekday
func WeekdayInt(s string) time.Weekday {
switch RecurrenceWeekday(s) {
case SundayRecurrenceWeekday:
case MondayRecurrenceWeekday:
case TuesdayRecurrenceWeekday:
case WednesdayRecurrenceWeekday:
case ThursdayRecurrenceWeekday:
case FridayRecurrenceWeekday:
case SaturdayRecurrenceWeekday:
GetWeekRuleRecurrenceTime()
GetWeekRuleRecurrenceTime2()
GetWeekRuleRecurrenceTime3()
GetWeekRuleRecurrenceTime4()
GetWeekRuleRecurrenceTime11()
GetWeekRuleRecurrenceTime22()
GetWeekRuleRecurrenceTime33()
GetWeekRuleRecurrenceTime44()
GetMonthRuleRecurrenceTime()
GetMonthRuleRecurrenceTime2()
GetMonthRuleRecurrenceTime3()
GetMonthRuleRecurrenceTime4()
GetMonthRuleRecurrenceTime11()
GetMonthRuleRecurrenceTime22()
GetMonthRuleRecurrenceTime33()
GetMonthRuleRecurrenceTime44()
func GetWeekRuleRecurrenceTime() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime2() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek2...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
recurr.ByDay = "TU,WE,SU"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime3() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek3...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime4() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek4...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime11() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek11 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek11...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime22() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek22...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
recurr.ByDay = "TU,WE,SU"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime33() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek33...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetWeekRuleRecurrenceTime44() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeWeek cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeWeek44...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "weekly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth1...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime2() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth2 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth2...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6,25,26,28"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime3() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth3 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth3...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6,24,25,26,28"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime4() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth4 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth4...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime11() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth11...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime22() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth2 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth22...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6,25,26,28"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime33() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth3 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth3...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
recurr.ByMonthDay = "2,3,4,5,6,24,25,26,28"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)
func GetMonthRuleRecurrenceTime44() {
cost := time.Since(start)
fmt.Println("TestGetRecurrenceTimeMonth4 cost=", cost)
fmt.Println("####################TestGetRecurrenceTimeMonth44...")
loc, _ := time.LoadLocation("Asia/Shanghai")
fstStartTime := int64(1661331600)
fstEndTime := int64(1661335200)
recurr := TRecurrenceInfo{}
recurr.Frequency = "monthly"
for i := 0; i <= 10; i++ {
start, end := recurr.GetRecurrenceTime(int64(i), fstStartTime, fstEndTime, loc)
fmt.Println("start:", start, "end:", end)