384 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			384 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package when
 | 
						||
 | 
						||
import (
 | 
						||
	"b612.me/startimer"
 | 
						||
	"errors"
 | 
						||
	"regexp"
 | 
						||
	"strconv"
 | 
						||
	"strings"
 | 
						||
	"time"
 | 
						||
)
 | 
						||
 | 
						||
func legalCheck(limitCode string, baseDate time.Time, opts ...startimer.TimerOptions) (startimer.StarTimer, error) {
 | 
						||
	if limitCode == "" {
 | 
						||
		return startimer.NewTimer(baseDate, opts...)
 | 
						||
	}
 | 
						||
	timer, err := startimer.NewTimer(baseDate, opts...)
 | 
						||
	if err != nil {
 | 
						||
		return timer, err
 | 
						||
	}
 | 
						||
	if strings.Contains(limitCode, "今") {
 | 
						||
		if timer.NextTimer().Day() != time.Now().Day() {
 | 
						||
			return timer, errors.New("无法添加,指定的提醒时刻不在未来。")
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return timer, err
 | 
						||
}
 | 
						||
 | 
						||
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{0,4}年)?(\d{0,5}个?月)?(\d{0,4}[明后大]{0,4}[日号天])?([今天日上中下午夜早凌清晨傍晚里]+)?(\d{1,4}个?[点小时钟::]+)?(\d{0,4}半?[分::秒]?钟?)?(\d{0,10}半?秒?钟?)?(后)?`)
 | 
						||
	if reg.MatchString(str) {
 | 
						||
		pts := reg.FindStringSubmatch(str)
 | 
						||
		setAsDate := false
 | 
						||
		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 {
 | 
						||
				if getNumbers(pts[2]) == 0 {
 | 
						||
					setAsDate = true
 | 
						||
				} else {
 | 
						||
					duration += time.Hour * 24 * 365 * time.Duration(getNumbers(pts[2]))
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
		if pts[3] != "" {
 | 
						||
			if !rpt.Every || setAsDate {
 | 
						||
				rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MONTH, Value: uint32(getNumbers(pts[3]))})
 | 
						||
			} else {
 | 
						||
				if getNumbers(pts[3]) == 0 {
 | 
						||
					setAsDate = true
 | 
						||
				} else {
 | 
						||
					duration += time.Hour * 24 * 30 * time.Duration(getNumbers(pts[3]))
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
		if pts[4] != "" {
 | 
						||
			now := time.Now()
 | 
						||
			switch pts[4] {
 | 
						||
			case "天":
 | 
						||
				if rpt.Every {
 | 
						||
					setAsDate = true
 | 
						||
				}
 | 
						||
			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 setAsDate == 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]))
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		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 hour < 12 && (timeParse == "下午" || strings.Contains(timeParse, "晚") || strings.Contains(timeParse, "夜")) {
 | 
						||
				hour += 12
 | 
						||
			}
 | 
						||
			if rpt.Every == setAsDate {
 | 
						||
				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 pts[7] == "半" {
 | 
						||
				pts[7] = "30"
 | 
						||
			}
 | 
						||
			model := startimer.STAR_MINUTE
 | 
						||
			tmodel := time.Minute
 | 
						||
			if strings.Contains(pts[7], "秒") {
 | 
						||
				model = startimer.STAR_SECOND
 | 
						||
				tmodel = time.Second
 | 
						||
			}
 | 
						||
			if rpt.Every == setAsDate {
 | 
						||
				rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: model, Value: uint32(getNumbers(pts[7]))})
 | 
						||
			} else if rpt.Every && !setAsDate {
 | 
						||
				duration += tmodel * time.Duration(uint32(getNumbers(pts[7])))
 | 
						||
			} else {
 | 
						||
				base.Add(tmodel * time.Duration(uint32(getNumbers(pts[7]))))
 | 
						||
			}
 | 
						||
		} else if hour != 0 || pts[5] != "" {
 | 
						||
			if rpt.Every == setAsDate {
 | 
						||
				rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0})
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		if pts[8] != "" {
 | 
						||
			if pts[8] == "半" {
 | 
						||
				pts[8] = "30"
 | 
						||
			}
 | 
						||
			if rpt.Every == setAsDate {
 | 
						||
				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 || pts[5] != "" || pts[7] != "" {
 | 
						||
			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 legalCheck(timeParse, time.Now(), startimer.WithStaticDate(now), startimer.WithRunCountLimit(count))
 | 
						||
		}
 | 
						||
		if duration.Seconds() > 0 {
 | 
						||
			rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(duration.Seconds())})
 | 
						||
		}
 | 
						||
		if rpt.Every == setAsDate {
 | 
						||
			rpt.Every = false
 | 
						||
		}
 | 
						||
		return legalCheck(timeParse, base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count))
 | 
						||
	}
 | 
						||
	return startimer.StarTimer{}, errors.New("no Match")
 | 
						||
}
 | 
						||
 | 
						||
func matchPeroidPattern02(base time.Time, str string) (startimer.StarTimer, error) {
 | 
						||
	preReg := "(周|礼拜|星期)([1-7一二三四五六七日天])([0-9一二三四五六七八九零])"
 | 
						||
	preExp := regexp.MustCompile(preReg)
 | 
						||
	if preExp.MatchString(str) {
 | 
						||
		str = preExp.ReplaceAllString(str, "${1}${2}的${3}")
 | 
						||
	}
 | 
						||
	str = transChn(str)
 | 
						||
	str = strings.ReplaceAll(str, "周日", "周0")
 | 
						||
	str = strings.ReplaceAll(str, "礼拜天", "周0")
 | 
						||
	str = strings.ReplaceAll(str, "星期日", "周0")
 | 
						||
	str = strings.ReplaceAll(str, "星期天", "周0")
 | 
						||
	str = strings.ReplaceAll(str, "周天", "周0")
 | 
						||
	var rpt startimer.Repeats
 | 
						||
	reg := regexp.MustCompile(`(每)?([周星期礼拜日天]\d{0,1})到?([周礼拜星期日天]?\d{0,1})?的?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}[个点时::]+)?(\d{0,4}[分半::]?钟?)?(\d{1,10}秒?钟?)?`)
 | 
						||
	if reg.MatchString(str) {
 | 
						||
		pts := reg.FindStringSubmatch(str)
 | 
						||
		scs := len(strings.Split(pts[0], "周"))
 | 
						||
		if scs > 3 {
 | 
						||
			return startimer.StarTimer{}, errors.New("Invalid stings")
 | 
						||
		}
 | 
						||
		if scs == 3 && !strings.Contains(pts[0], "到") {
 | 
						||
			return startimer.StarTimer{}, errors.New("Invalid stings")
 | 
						||
		}
 | 
						||
		if pts[2] != "" {
 | 
						||
			if len(pts[3]) != 0 {
 | 
						||
				startWk := getNumbers(pts[2])
 | 
						||
				endWk := getNumbers(pts[3])
 | 
						||
				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)})
 | 
						||
				}
 | 
						||
			} else {
 | 
						||
				wkNum := getNumbers(pts[2])
 | 
						||
				rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(wkNum)})
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		timeParse := pts[4]
 | 
						||
		var hour uint32
 | 
						||
		if pts[5] != "" {
 | 
						||
			hour = uint32(getNumbers(pts[5]))
 | 
						||
			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[6] != "" {
 | 
						||
			if pts[6] == "半" {
 | 
						||
				pts[6] = "30"
 | 
						||
			}
 | 
						||
			rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: uint32(getNumbers(pts[6]))})
 | 
						||
		} else if hour != 0 {
 | 
						||
			rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0})
 | 
						||
		}
 | 
						||
		if pts[7] != "" {
 | 
						||
			rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(getNumbers(pts[7]))})
 | 
						||
		} 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))
 | 
						||
	}
 | 
						||
	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
 | 
						||
}
 |