go 正则解析字符串的时间窗范围 通过分组分别取年、月、日、时、分、秒

发布时间 2023-06-29 22:22:04作者: zhangmingda

背景

需求: 将时间窗开始和结束时间提取出来,存储到数据库

 

难点: 获取割接公告操作时间窗范围, 格式有一定动态变化,日期、月份偶尔是1位数,

bodyContent1 := "您好!由于XXXXX机房一台网络设备存在安全隐患,我司计划于 2023年06月30日 00:30 - 03:00  到 对网络设备进行割接升级消除网络隐患,割接期间,对XXXXX个别连接会出现网络闪断。对于此次割接工程给贵司带来的影响和不便,我们深表歉意!"
bodyContent2 := "您好!为优化xxxx服务质量,计划于2023年06月5日22:00~2023年06月6日02:00云监控服务升级。升级期间可能短时间影响告警判定和"

解决方案:正则表达式分组,只取命名分组的值

package main

import (
    "fmt"
    "regexp"
    "time"
)

// ParseContentTimeWindow 解析字符串中的时间窗范围
func ParseContentTimeWindow(content string) (actionTimeWin map[string]string) {

    // map 类型必须先make后进行初始化,否则地址对应值为null,无法继续赋值
    actionTimeWin = make(map[string]string)

    // 按照正则截取字符串,时间窗字符串日期和时间之间 两个时间之间的-或者~两侧可能有空格,也可能没有空格,使用正则可以统配处理
    // 正则可以分组,将年月日,时分都按照分组进行命名取出来
    oneDayReMustCompile := regexp.MustCompile("(?P<year>\\d+)年(?P<month>\\d+)月(?P<day>\\d+)日 *(?P<startHour>\\d+):(?P<startMin>\\d+) *[-~]+ *(?P<endHour>\\d+):(?P<endMin>\\d+)")
    acrossDayReMustCompile := regexp.MustCompile("(?P<startYear>\\d+)年(?P<startMonth>\\d+)月(?P<startDay>\\d+)日 *(?P<startHour>\\d+):(?P<startMin>\\d+) *[-~]+ *(?P<endYear>\\d+)年(?P<endMonth>\\d+)月(?P<endDay>\\d+)日 *(?P<endHour>\\d+):(?P<endMin>\\d+)")
    if oneDayReMustCompile.MatchString(content) {
        //fmt.Println("匹配上了当天")
        match := oneDayReMustCompile.FindStringSubmatch(content)
        groupNames := oneDayReMustCompile.SubexpNames()
        // 转换为map
        for i, name := range groupNames {
            if i != 0 && name != "" { // 第一个分组为空(也就是整个匹配)
                value := match[i]
                if len(value) == 1 {
                    value = "0" + match[i]
                }
                actionTimeWin[name] = value
            }
        }
        date := actionTimeWin["year"] + "-" + actionTimeWin["month"] + "-" + actionTimeWin["day"]     //从分组取出日期
        startDateTimeStr := date + " " + actionTimeWin["startHour"] + ":" + actionTimeWin["startMin"] //从分组取出时间字段
        endDateTimeStr := date + " " + actionTimeWin["endHour"] + ":" + actionTimeWin["endMin"]       //从分组取出时间字段
        //fmt.Println("startDateTimeStr:", startDateTimeStr)
        //fmt.Println("endDateTimeStr:", endDateTimeStr)
        startTime, _ := time.Parse("2006-01-02 15:04", startDateTimeStr) // 返回Time类型
        endTime, _ := time.Parse("2006-01-02 15:04", endDateTimeStr)     // 返回Time类型
        startDateTime := startTime.Format("2006-01-02 15:04:05")         // 格式化输出数据库存储格式
        endDateTime := endTime.Format("2006-01-02 15:04:05")             // 格式化输出数据库存储格式
        actionTimeWin["startDateTime"] = startDateTime
        actionTimeWin["endDateTime"] = endDateTime
        //fmt.Println("startDateTime:", startDateTime)
        //fmt.Println("endDateTime:", endDateTime)

    } else if acrossDayReMustCompile.MatchString(content) {
        //fmt.Println("匹配上了跨天")
        match := acrossDayReMustCompile.FindStringSubmatch(content)
        groupNames := acrossDayReMustCompile.SubexpNames()
        // 转换为map
        for i, name := range groupNames {
            if i != 0 && name != "" { // 第一个分组为空(也就是整个匹配)
                value := match[i]
                if len(value) == 1 {
                    value = "0" + match[i]
                }
                actionTimeWin[name] = value
            }
        }
        startDate := actionTimeWin["startYear"] + "-" + actionTimeWin["startMonth"] + "-" + actionTimeWin["startDay"]
        endDate := actionTimeWin["endYear"] + "-" + actionTimeWin["endMonth"] + "-" + actionTimeWin["endDay"]
        startDateTimeStr := startDate + " " + actionTimeWin["startHour"] + ":" + actionTimeWin["startMin"] //从分组取出日期时间字段
        endDateTimeStr := endDate + " " + actionTimeWin["endHour"] + ":" + actionTimeWin["endMin"]         //从分组取出日期时间字段
        //fmt.Println("startDateTimeStr:", startDateTimeStr)
        //fmt.Println("endDateTimeStr:", endDateTimeStr)
        startTime, _ := time.Parse("2006-01-02 15:04", startDateTimeStr) // 返回Time类型
        endTime, _ := time.Parse("2006-01-02 15:04", endDateTimeStr)     // 返回Time类型
        startDateTime := startTime.Format("2006-01-02 15:04:05")         // 格式化输出数据库存储格式
        endDateTime := endTime.Format("2006-01-02 15:04:05")             // 格式化输出数据库存储格式
        //fmt.Println("startDateTime:", startDateTime)
        //fmt.Println("endDateTime:", endDateTime)
        actionTimeWin["startDateTime"] = startDateTime
        actionTimeWin["endDateTime"] = endDateTime
    }
    return
}

func main() {
    bodyContent1 := "您好!由于上海鹏博士机房一台网络设备存在安全隐患,我司计划于 2023年6月30日 00:30 - 03:00  到 对网络设备进行割接升级消除网络隐患,割接期间,对象存储KS3个别连接会出现网络闪断。对于此次割接工程给贵司带来的影响和不便,我们深表歉意!"
    bodyContent2 := "您好!为优化xxxx服务质量,计划于2023年06月5日22:00~2023年06月6日02:00云监控服务升级。升级期间可能短时间影响告警判定和"
    // 测试解析时间窗
    actionTimeWin := ParseContentTimeWindow(bodyContent1)
    fmt.Println(actionTimeWin["startDateTime"]) //2023-06-30 00:30:00
    fmt.Println(actionTimeWin["endDateTime"])   //2023-06-30 03:00:00
    actionTimeWin2 := ParseContentTimeWindow(bodyContent2)
    fmt.Println(actionTimeWin2["startDateTime"]) //2023-06-05 22:00:00
    fmt.Println(actionTimeWin2["endDateTime"])   //2023-06-06 02:00:00
}