package when import ( "b612.me/startimer" "errors" "regexp" "strconv" "strings" "time" ) func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, error) { str = transChn(str) var rpt startimer.Repeats var duration time.Duration reg := regexp.MustCompile(`(每隔|每)?(\d{1,4}年)?(\d{1,5}个?月)?(\d{1,4}[明后大]{0,4}[日号天])?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}个?[点小时钟:]+)?(\d{1,4}[分:])?(\d{1,10}秒?)?(后)?`) if reg.MatchString(str) { pts := reg.FindStringSubmatch(str) var timeParse = pts[5] count := 1 if pts[1] != "" { rpt.Every = true count = 0 } if pts[2] != "" { if !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_YEAR, Value: uint32(getNumbers(pts[2]))}) } else { duration += time.Hour * 24 * 365 * time.Duration(getNumbers(pts[2])) } } if pts[3] != "" { if !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MONTH, Value: uint32(getNumbers(pts[3]))}) } else { duration += time.Hour * 24 * 30 * time.Duration(getNumbers(pts[3])) } } if pts[4] != "" { now := time.Now() switch pts[4] { case "明天": rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 24).Day())}) case "后天": rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 48).Day())}) case "大后天": rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 72).Day())}) case "大大后天": rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 96).Day())}) default: if !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(getNumbers(pts[4]))}) } else { duration += time.Hour * 24 * time.Duration(getNumbers(pts[4])) } } } setAsDate := false if rpt.Every && timeParse != "" { setAsDate = true } else if rpt.Every && !strings.Contains(pts[6], "小时") { setAsDate = true base = time.Date(base.Year(), base.Month(), base.Day(), 0, 0, 0, 0, base.Location()) } var hour uint32 if pts[6] != "" { hour = uint32(getNumbers(pts[6])) if timeParse == "下午" || strings.Contains(timeParse, "晚") || strings.Contains(timeParse, "夜") { hour += 12 } if !setAsDate && !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_HOUR, Value: hour}) } else if rpt.Every && !setAsDate { duration += time.Hour * time.Duration(hour) } else { base.Add(time.Hour * time.Duration(hour)) } } else if timeParse != "" { switch timeParse { case "上午": hour = 9 case "中午": hour = 8 case "下午": hour = 15 case "傍晚": hour = 18 case "夜里", "晚上", "晚", "夜", "夜晚": hour = 21 case "凌晨": hour = 0 case "清晨": hour = 6 } if !setAsDate { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_HOUR, Value: hour}) } else { base.Add(time.Hour * time.Duration(hour)) } } if pts[7] != "" { if !setAsDate && !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: uint32(getNumbers(pts[7]))}) } else if rpt.Every && !setAsDate { duration += time.Minute * time.Duration(uint32(getNumbers(pts[7]))) } else { base.Add(time.Minute * time.Duration(uint32(getNumbers(pts[7])))) } } else if hour != 0 { if !rpt.Every && !setAsDate { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0}) } } if pts[8] != "" { if !setAsDate && !rpt.Every { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(getNumbers(pts[8]))}) } else if rpt.Every && !setAsDate { duration += time.Second * time.Duration(uint32(getNumbers(pts[8]))) } else { base.Add(time.Second * time.Duration(uint32(getNumbers(pts[8])))) } } else if hour != 0 { if !rpt.Every && !setAsDate { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: 0}) } } if pts[9] != "" { if rpt.Every { return startimer.StarTimer{}, errors.New("Invalid Setences") } now := time.Now() for _, sr := range rpt.Repeat { switch sr.Unit { case startimer.STAR_YEAR: now = now.AddDate(int(sr.Value), 0, 0) case startimer.STAR_MONTH: now = now.AddDate(0, int(sr.Value), 0) case startimer.STAR_DAY: now = now.AddDate(0, 0, int(sr.Value)) case startimer.STAR_HOUR: now = now.Add(time.Duration(sr.Value) * time.Hour) case startimer.STAR_MINUTE: now = now.Add(time.Duration(sr.Value) * time.Minute) case startimer.STAR_SECOND: now = now.Add(time.Duration(sr.Value) * time.Second) } } return startimer.NewTimer(time.Now(), startimer.WithStaticDate(now), startimer.WithRunCountLimit(count)), nil } if duration.Seconds() > 0 { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(duration.Seconds())}) } return startimer.NewTimer(base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count)), nil } return startimer.StarTimer{}, errors.New("no Match") } func matchPeroidPattern02(base time.Time, str string) (startimer.StarTimer, error) { str = transChn(str) var rpt startimer.Repeats reg := regexp.MustCompile(`(每)?([周星期礼拜][周礼拜星期到1-6日天]+)+的?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}[个点时:]+)?(\d{1,4}[分:])?(\d{1,10}秒?)?`) if reg.MatchString(str) { pts := reg.FindStringSubmatch(str) if pts[2] != "" { wk := strings.ReplaceAll(pts[2], "周日", "周0") wk = strings.ReplaceAll(wk, "礼拜天", "周0") wk = strings.ReplaceAll(wk, "星期日", "周0") wk = strings.ReplaceAll(wk, "星期天", "周0") wk = strings.ReplaceAll(wk, "周天", "周0") if strings.Contains(wk, "到") { pk := strings.Split(wk, "到") startWk := getNumbers(pk[0]) endWk := getNumbers(pk[1]) if endWk < startWk { endWk += 7 } for i := startWk; i <= endWk; i++ { num := i if num > 6 { num -= 7 } rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(num)}) } } } timeParse := pts[3] var hour uint32 if pts[4] != "" { hour = uint32(getNumbers(pts[4])) if timeParse == "下午" || strings.Contains(timeParse, "晚") || strings.Contains(timeParse, "夜") { hour += 12 } rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_HOUR, Value: hour}) } else if timeParse != "" { switch timeParse { case "上午": hour = 9 case "中午": hour = 8 case "下午": hour = 15 case "傍晚": hour = 18 case "夜里", "晚上", "晚", "夜", "夜晚": hour = 21 case "凌晨": hour = 0 case "清晨": hour = 6 } rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_HOUR, Value: hour}) } if pts[5] != "" { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: uint32(getNumbers(pts[5]))}) } else if hour != 0 { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0}) } if pts[6] != "" { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(getNumbers(pts[6]))}) } else if hour != 0 { rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: 0}) } count := 1 if pts[1] != "" { count = 0 } return startimer.NewTimer(base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count)), nil } return startimer.StarTimer{}, errors.New("no Match") } func WhenWithPeriod(str string) (startimer.StarTimer, error) { if match, _ := regexp.MatchString(`(周|星期|礼拜)[一二三四五六天日]`, str); match { return matchPeroidPattern02(time.Now(), str) } return matchPeriodPattern01(time.Now(), str) } func transChn(msg string) string { var res []rune var tmpMap []rune keyMap := map[rune]int{ '零': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10, '百': 100, '千': 1000, '万': 10000, '亿': 100000000, '两': 2, '俩': 2, } for _, v := range []rune(msg) { if _, ok := keyMap[v]; ok { tmpMap = append(tmpMap, v) } else { if len(tmpMap) != 0 { res = append(res, []rune(strconv.Itoa(transfer(string(tmpMap))))...) tmpMap = []rune{} } res = append(res, v) } } return string(res) } func transfer(msg string) int { keyMap := map[rune]int{ '零': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10, '百': 100, '千': 1000, '万': 10000, '亿': 100000000, '两': 2, '俩': 2, } result := 0 secCache := 0 thrCache := 0 fKWord := map[rune]int{'百': 100, '千': 1000, '万': 10000, '亿': 100000000} for _, num := range []rune(msg) { if _, match := fKWord[num]; !match { if num == '十' && thrCache != 0 { thrCache *= keyMap[num] } else { thrCache += keyMap[num] } } else { if fKWord[num] < 10000 { secCache += thrCache * fKWord[num] thrCache = 0 } else { secCache += thrCache thrCache = 0 if secCache == 0 { result *= fKWord[num] continue } result += secCache * fKWord[num] secCache = 0 } } } result += secCache + thrCache return result } func getNumbers(s string) float64 { res := "" isNegative := false for _, c := range s { switch { case c == '-' && len(res) == 0: isNegative = true case c >= '0' && c <= '9': res += string(c) case c == '.' && !strings.Contains(res, "."): res += string(c) } } if res == "" { return 0 } if isNegative { res = "-" + res } num, _ := strconv.ParseFloat(res, 64) return num }