You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
12 KiB
Go

2 years ago
package when
2 years ago
import (
"b612.me/startimer"
2 years ago
"errors"
2 years ago
"regexp"
"strconv"
"strings"
"time"
)
1 year ago
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
}
2 years ago
func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, error) {
2 years ago
str = transChn(str)
var rpt startimer.Repeats
var duration time.Duration
1 year ago
reg := regexp.MustCompile(`(每隔|每)?(\d{0,4}年)?(\d{0,5}个?月)?(\d{0,4}[明后大]{0,4}[日号天])?([今天日上中下午夜早凌清晨傍晚里]+)?(\d{1,4}个?[点小时钟:]+)?(\d{0,4}半?[分::秒]?钟?)?(\d{0,10}半?秒?钟?)?(后)?`)
2 years ago
if reg.MatchString(str) {
pts := reg.FindStringSubmatch(str)
2 years ago
setAsDate := false
2 years ago
var timeParse = pts[5]
2 years ago
count := 1
2 years ago
if pts[1] != "" {
rpt.Every = true
2 years ago
count = 0
2 years ago
}
if pts[2] != "" {
if !rpt.Every {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_YEAR, Value: uint32(getNumbers(pts[2]))})
} else {
2 years ago
if getNumbers(pts[2]) == 0 {
setAsDate = true
} else {
duration += time.Hour * 24 * 365 * time.Duration(getNumbers(pts[2]))
}
2 years ago
}
}
if pts[3] != "" {
2 years ago
if !rpt.Every || setAsDate {
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MONTH, Value: uint32(getNumbers(pts[3]))})
} else {
2 years ago
if getNumbers(pts[3]) == 0 {
setAsDate = true
} else {
duration += time.Hour * 24 * 30 * time.Duration(getNumbers(pts[3]))
}
2 years ago
}
}
if pts[4] != "" {
now := time.Now()
switch pts[4] {
2 years ago
case "天":
if rpt.Every {
setAsDate = true
}
1 year ago
case "明天", "明日":
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 24).Day())})
1 year ago
case "后天", "后日":
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 48).Day())})
1 year ago
case "大后天", "大后日":
2 years ago
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:
2 years ago
if setAsDate == rpt.Every {
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(getNumbers(pts[4]))})
2 years ago
} else {
duration += time.Hour * 24 * time.Duration(getNumbers(pts[4]))
}
}
}
2 years ago
2 years ago
if rpt.Every && timeParse != "" {
setAsDate = true
}
2 years ago
//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())
// }
2 years ago
var hour uint32
2 years ago
if pts[6] != "" {
2 years ago
hour = uint32(getNumbers(pts[6]))
1 year ago
if hour < 12 && (timeParse == "下午" || strings.Contains(timeParse, "晚") || strings.Contains(timeParse, "夜")) {
2 years ago
hour += 12
}
2 years ago
if rpt.Every == setAsDate {
2 years ago
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] != "" {
2 years ago
if pts[7] == "半" {
pts[7] = "30"
}
2 years ago
model := startimer.STAR_MINUTE
tmodel := time.Minute
if strings.Contains(pts[7], "秒") {
model = startimer.STAR_SECOND
tmodel = time.Second
}
2 years ago
if rpt.Every == setAsDate {
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: model, Value: uint32(getNumbers(pts[7]))})
2 years ago
} else if rpt.Every && !setAsDate {
2 years ago
duration += tmodel * time.Duration(uint32(getNumbers(pts[7])))
2 years ago
} else {
2 years ago
base.Add(tmodel * time.Duration(uint32(getNumbers(pts[7]))))
2 years ago
}
1 year ago
} else if hour != 0 || pts[5] != "" {
2 years ago
if rpt.Every == setAsDate {
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0})
}
2 years ago
}
2 years ago
2 years ago
if pts[8] != "" {
2 years ago
if pts[8] == "半" {
pts[8] = "30"
}
2 years ago
if rpt.Every == setAsDate {
2 years ago
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]))))
}
1 year ago
} else if hour != 0 || pts[5] != "" || pts[7] != "" {
2 years ago
if rpt.Every == setAsDate {
2 years ago
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)
}
}
1 year ago
return legalCheck(timeParse, time.Now(), startimer.WithStaticDate(now), startimer.WithRunCountLimit(count))
2 years ago
}
if duration.Seconds() > 0 {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(duration.Seconds())})
}
2 years ago
if rpt.Every == setAsDate {
rpt.Every = false
}
1 year ago
return legalCheck(timeParse, base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count))
2 years ago
}
2 years ago
return startimer.StarTimer{}, errors.New("no Match")
2 years ago
}
2 years ago
func matchPeroidPattern02(base time.Time, str string) (startimer.StarTimer, error) {
1 year ago
preReg := "(周|礼拜|星期)([1-7一二三四五六七日天])([0-9一二三四五六七八九零])"
preExp := regexp.MustCompile(preReg)
if preExp.MatchString(str) {
str = preExp.ReplaceAllString(str, "${1}${2}的${3}")
}
2 years ago
str = transChn(str)
1 year ago
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")
2 years ago
var rpt startimer.Repeats
1 year ago
reg := regexp.MustCompile(`(每)?([周星期礼拜日天]\d{0,1})到?([周礼拜星期日天]?\d{0,1})?的?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}[个点时::]+)?(\d{0,4}[分半:]?钟?)?(\d{1,10}秒?钟?)?`)
2 years ago
if reg.MatchString(str) {
pts := reg.FindStringSubmatch(str)
1 year ago
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")
}
2 years ago
if pts[2] != "" {
1 year ago
if len(pts[3]) != 0 {
startWk := getNumbers(pts[2])
endWk := getNumbers(pts[3])
2 years ago
if endWk < startWk {
endWk += 7
}
for i := startWk; i <= endWk; i++ {
num := i
if num > 6 {
num -= 7
2 years ago
}
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(num)})
2 years ago
}
2 years ago
} else {
1 year ago
wkNum := getNumbers(pts[2])
2 years ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(wkNum)})
2 years ago
}
}
2 years ago
1 year ago
timeParse := pts[4]
2 years ago
var hour uint32
1 year ago
if pts[5] != "" {
hour = uint32(getNumbers(pts[5]))
2 years ago
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})
}
1 year ago
if pts[6] != "" {
if pts[6] == "半" {
pts[6] = "30"
2 years ago
}
1 year ago
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: uint32(getNumbers(pts[6]))})
2 years ago
} else if hour != 0 {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0})
}
1 year ago
if pts[7] != "" {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(getNumbers(pts[7]))})
2 years ago
} else if hour != 0 {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: 0})
}
count := 1
if pts[1] != "" {
count = 0
}
1 year ago
return startimer.NewTimer(base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count))
2 years ago
}
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)
2 years ago
}
2 years ago
return matchPeriodPattern01(time.Now(), str)
2 years ago
}
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
}