init
This commit is contained in:
commit
ce84ad4f01
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
9
.idea/candy.iml
generated
Normal file
9
.idea/candy.iml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/candy.iml" filepath="$PROJECT_DIR$/.idea/candy.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
232
remind/parse.go
Normal file
232
remind/parse.go
Normal file
@ -0,0 +1,232 @@
|
||||
package remind
|
||||
|
||||
import (
|
||||
"b612.me/startimer"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func matchPattern01(str string) (startimer.StarTimer, bool) {
|
||||
str = transChn(str)
|
||||
var base = time.Now()
|
||||
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]
|
||||
if pts[1] != "" {
|
||||
rpt.Every = true
|
||||
}
|
||||
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_MONTH, 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())
|
||||
}
|
||||
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 != "" {
|
||||
var hour uint32
|
||||
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]))))
|
||||
}
|
||||
|
||||
}
|
||||
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]))))
|
||||
}
|
||||
}
|
||||
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)), true
|
||||
}
|
||||
return startimer.StarTimer{}, false
|
||||
}
|
||||
|
||||
/*
|
||||
func matchPattern02(str string) (startimer.Repeats, bool) {
|
||||
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[1] != "" {
|
||||
rpt.Every = true
|
||||
}
|
||||
if pts[2] != "" {
|
||||
if strings.Contains(pts[2], "到") {
|
||||
se := strings.Split(pts[2], "到")
|
||||
start := getNumbers(se[0])
|
||||
end := getNumbers(se[1])
|
||||
if end >= start {
|
||||
for i := start; i <= end; i++ {
|
||||
startimer.NextDayOfWeek()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
15
remind/parse_test.go
Normal file
15
remind/parse_test.go
Normal file
@ -0,0 +1,15 @@
|
||||
package remind
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
a, _ := matchPattern01("每两个小时")
|
||||
fmt.Println(a.NextTimer(), a.BaseDate())
|
||||
a, _ = matchPattern01("每五个月零二十五天三小时25分15秒")
|
||||
fmt.Println(a.NextTimer(), a.BaseDate())
|
||||
a, _ = matchPattern01("5月23日3点24分12秒")
|
||||
fmt.Println(a.NextTimer(), a.BaseDate())
|
||||
}
|
227
remind/sample.txt
Normal file
227
remind/sample.txt
Normal file
@ -0,0 +1,227 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tests := []string{"明天下午三点", "每两天两个小时", "每天上午", "周五上午", "每周四下午三点", "2023年6月18日上午8点49", "大后天的16:00", "每隔5天提醒我吃饭", "从后天上午9点开始,每3天"}
|
||||
|
||||
for _, test := range tests {
|
||||
fmt.Printf("测试文本:%s\n", test)
|
||||
|
||||
// 匹配时间模板
|
||||
pattern1 := `(?P<y>\d{4})年(?P<mo>\d{1,2})月(?P<d>\d{1,2})日(?P<h>\d{1,2}):(?P<mi>\d{1,2})`
|
||||
pattern2 := `(每)?((?P<day>\d+)天)?((?P<hour>\d+)个小时)?((?P<min>\d+)分)?((?P<sec>\d+)秒)?(后|钟|日)?`
|
||||
pattern3 := `(?P<week>周[一二三四五六日])?((?P<ampm>[上中下])*午)?(?P<hour2>\d{1,2}):?(?P<mi2>\d{0,2})`
|
||||
pattern4 := `每((?P<day2>[天周])[一二三四五六七八九十]+)?(?P<hour3>\d{1,2}):(?P<mi3>\d{2})`
|
||||
pattern5 := `(?P<date2>[今明后大]?[0-9]{0,2}年[0-9]{0,2}月[0-9]{0,2}日)?(?P<week2>周[一二三四五六日])?((?P<ampm2>[上中下])*午)?(?P<hour4>\d{1,2}):?(?P<mi4>\d{0,2})`
|
||||
|
||||
match1, _ := regexp.MatchString(pattern1, test)
|
||||
match2, _ := regexp.MatchString(pattern2, test)
|
||||
match3, _ := regexp.MatchString(pattern3, test)
|
||||
match4, _ := regexp.MatchString(pattern4, test)
|
||||
match5, _ := regexp.MatchString(pattern5, test)
|
||||
|
||||
// 判断是否存在循环提醒
|
||||
isLoop := false
|
||||
if match2 {
|
||||
isLoop = matchDayHourMinSecLoop(test)
|
||||
} else if match4 {
|
||||
isLoop = matchEveryDayLoop(test)
|
||||
} else if match5 {
|
||||
isLoop = matchStartLoop(test)
|
||||
}
|
||||
|
||||
if match1 || match2 || match3 || match4 || match5 {
|
||||
fmt.Println("匹配到时间!")
|
||||
if isLoop {
|
||||
fmt.Println("存在循环提醒!")
|
||||
} else {
|
||||
fmt.Println("不存在循环提醒!")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("未匹配到时间!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断每天、每两天、每小时、每分钟循环提醒
|
||||
func matchDayHourMinSecLoop(text string) bool {
|
||||
pattern := `(每)?((?P<day>\d+)天)?((?P<hour>\d+)个小时)?((?P<min>\d+)分)?((?P<sec>\d+)秒)?(后|钟|日)?`
|
||||
re := regexp.MustCompile(pattern)
|
||||
match := re.FindStringSubmatch(text)
|
||||
|
||||
// 判断是否存在循环提醒
|
||||
for _, group := range match[1:] {
|
||||
if len(group) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 判断每天、每周循环提醒
|
||||
func matchEveryDayLoop(text string) bool {
|
||||
pattern := `每((?P<day>[天周])[一二三四五六七八九十]+)?(?P<hour>\d{1,2}):(?P<mi>\d{2})`
|
||||
re := regexp.MustCompile(pattern)
|
||||
match := re.FindStringSubmatch(text)
|
||||
|
||||
if len(match[1]) > 0 || len(match[2]) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 判断从某个时间开始,每隔多长时间循环提醒
|
||||
func matchStartLoop(text string) bool {
|
||||
pattern := `(?P<date>[今明后大]?[0-9]{0,2}年[0-9]{0,2}月[0-9]{0,2}日)?(?P<week>周[一二三四五六日])?((?P<ampm>[上中下])*午)?(?P<hour>\d{1,2}):?(?P<mi>\d{0,2})开始,每隔(?P<loop>\d+)([天时分])(\d+)?(\w+)?(\d+秒)?`
|
||||
re := regexp.MustCompile(pattern)
|
||||
match := re.FindStringSubmatch(text)
|
||||
|
||||
loopDuration := parseDuration(match[2], match[3], match[4], match[5], match[6])
|
||||
if loopDuration > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 解析时间段
|
||||
func parseDuration(d, h, m, s, unit string) time.Duration {
|
||||
duration := time.Duration(0)
|
||||
|
||||
if len(d) > 0 {
|
||||
duration += 24 * time.Duration(parseInt(d)) * time.Hour
|
||||
}
|
||||
|
||||
if len(h) > 0 {
|
||||
duration += time.Duration(parseInt(h)) * time.Hour
|
||||
}
|
||||
|
||||
if len(m) > 0 {
|
||||
duration += time.Duration(parseInt(m)) * time.Minute
|
||||
}
|
||||
|
||||
if len(s) > 0 {
|
||||
duration += time.Duration(parseInt(s)) * time.Second
|
||||
}
|
||||
|
||||
switch unit {
|
||||
case "时":
|
||||
duration += time.Hour
|
||||
case "分":
|
||||
duration += time.Minute
|
||||
case "秒":
|
||||
duration += time.Second
|
||||
}
|
||||
|
||||
return duration
|
||||
}
|
||||
|
||||
// 将中文数字转换为整数
|
||||
func parseInt(chineseNum string) int {
|
||||
chineseNums := map[string]int{
|
||||
"零": 0,
|
||||
"一": 1,
|
||||
"二": 2,
|
||||
"三": 3,
|
||||
"四": 4,
|
||||
"五": 5,
|
||||
"六": 6,
|
||||
"七": 7,
|
||||
"八": 8,
|
||||
"九": 9,
|
||||
"十": 10,
|
||||
"两": 2, // 特殊情况,"两"表示2
|
||||
}
|
||||
|
||||
num := 0
|
||||
for i := 0; i < len(chineseNum); i++ {
|
||||
curNum := chineseNums[string(chineseNum[i])]
|
||||
if curNum == 10 {
|
||||
if num == 0 {
|
||||
num = 10
|
||||
} else {
|
||||
num *= 10
|
||||
}
|
||||
} else {
|
||||
num += curNum
|
||||
}
|
||||
}
|
||||
|
||||
return num
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tests := []string{"明天下午三点五十八秒", "每两天两个小时十分三秒", "每天上午零点", "周五上午一时", "每周四下午三点四十二秒", "2023年6月18日上午8点49分58秒", "大后天的16:00:23", "每隔5天提醒我吃饭", "从后天上午9点开始,每3天"}
|
||||
|
||||
// 模式1:日期时间模式,如:2021年8月1日下午3点20分
|
||||
pattern1 := `(\d{4}年\d{1,2}月\d{1,2}日)?([上中下午夜早]+)?(\d{1,2}[点时](\d{1,2}分)?(\d{1,2}秒)?)?`
|
||||
|
||||
// 模式2:大后天模式,如:大后天的16:00
|
||||
pattern2 := `[大明后](前|后)?天的(\d{1,2}:[0-5]\d:[0-5]\d)`
|
||||
|
||||
// 模式3:每隔多长时间模式,如:每两天两个小时,每隔5天提醒我吃饭
|
||||
pattern3 := `每隔(\d+)([天时分])(\d+)?(\w+)?(\d+秒)?`
|
||||
|
||||
// 模式4:频率模式,如:每天上午,周五上午,每周四下午三点
|
||||
pattern4 := `每([天周])?([一二三四五六七八九十]+)日?([上中下午夜早]+)?(\d{1,2}:[0-5]\d(:[0-5]\d)?)?`
|
||||
|
||||
// 模式5:从某个日期时间开始,每隔多长时间,如:从后天上午9点开始,每3天
|
||||
pattern5 := `从([大明后](前|后)?天的|今天|明天|后天|(\d{4}年\d{1,2}月\d{1,2}日))(\d{1,2}:[0-5]\d(:[0-5]\d)?)?开始,每隔(\d+)([天时分])(\d+)?(\w+)?(\d+秒)?`
|
||||
|
||||
for _, test := range tests {
|
||||
fmt.Printf("测试文本:%s\n", test)
|
||||
|
||||
match1, _ := regexp.MatchString(pattern1, test)
|
||||
if match1 {
|
||||
fmt.Println("匹配到时间!")
|
||||
} else {
|
||||
fmt.Println("未匹配到时间!")
|
||||
}
|
||||
|
||||
match2, _ := regexp.MatchString(pattern2, test)
|
||||
if match2 {
|
||||
fmt.Println("匹配到大后天!")
|
||||
}
|
||||
|
||||
match3, _ := regexp.MatchString(pattern3, test)
|
||||
if match3 {
|
||||
fmt.Println("匹配到每隔时间!")
|
||||
}
|
||||
|
||||
match4, _ := regexp.MatchString(pattern4, test)
|
||||
if match4 {
|
||||
fmt.Println("匹配到频率时间!")
|
||||
}
|
||||
|
||||
match5, _ := regexp.MatchString(pattern5, test)
|
||||
if match5 {
|
||||
fmt.Println("匹配到从某个时间开始,每隔多长时间!")
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user