golang自然语言日期时间解析插件when的使用

golang自然语言日期时间解析插件when的使用

when 是一个自然语言日期/时间解析器,具有可插拔的规则和合并策略。

示例

以下是一些自然语言日期时间表达式的示例:

  • tonight at 11:10 pm
  • at Friday afternoon
  • the deadline is next tuesday 14:00
  • drop me a line next wednesday at 2:25 p.m
  • it could be done at 11 am past tuesday

安装

要安装最新版本:

$ go get github.com/olebedev/when@latest

使用方法

基本用法

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules/common"
	"github.com/olebedev/when/rules/en"
)

func main() {
	// 创建when解析器实例
	w := when.New(nil)
	
	// 添加英文规则和通用规则
	w.Add(en.All...)
	w.Add(common.All...)

	// 要解析的文本
	text := "drop me a line in next wednesday at 2:25 p.m"
	
	// 解析文本,基于当前时间
	r, err := w.Parse(text, time.Now())
	if err != nil {
		// 处理错误
	}
	if r == nil {
		// 没有找到匹配的时间表达式
	}

	// 输出结果
	fmt.Println(
		"the time",
		r.Time.String(),
		"mentioned in",
		text[r.Index:r.Index+len(r.Text)],
	)
}

距离选项(Distance Option)

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules/common"
	"github.com/olebedev/when/rules/en"
	"github.com/olebedev/when/rules"
)

func main() {
	w := when.New(nil)
	w.Add(en.All...)
	w.Add(common.All...)

	text := "February 23, 2019 | 1:46pm"

	// 使用默认距离(5):
	// February 23, 2019 | 1:46pm
	//            └───┬───┘
	//           distance: 9 (1:46pm将被忽略)

	r, _ := w.Parse(text, time.Now())
	fmt.Printf(r.Time.String())
	// 输出: "2019-02-23 09:21:21.835182427 -0300 -03"
	// 2019-02-23 (正确)
	//   09:21:21 ("错误")

	// 使用自定义距离(10):
	w.SetOptions(&rules.Options{
		Distance:     10,
		MatchByOrder: true})

	r, _ = w.Parse(text, time.Now())
	fmt.Printf(r.Time.String())
	// 输出: "2019-02-23 13:46:21.559521554 -0300 -03"
	// 2019-02-23 (正确)
	//   13:46:21 (正确)
}

工作原理

解析器会检查所有规则并提取一组匹配的规则,这些规则之间的距离小于或等于默认的options.Distance(默认为5)。例如:

on next wednesday at 2:25 p.m.
   └──────┬─────┘    └───┬───┘
       weekday      hour + minute

这样我们就得到了一个匹配规则簇 - 在字符串表示中的"next wednesday at 2:25 p.m."。

支持的语言

  • EN - 英语
  • RU - 俄语
  • BR - 巴西葡萄牙语
  • ZH - 中文
  • NL - 荷兰语

项目状态

项目处于基本完成状态,已经在实际项目中使用。发现的问题会尽快修复。

许可证

Apache License 2.0


更多关于golang自然语言日期时间解析插件when的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang自然语言日期时间解析插件when的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 自然语言日期时间解析插件 when 的使用

when 是一个强大的自然语言日期时间解析库,可以将人类可读的日期时间字符串转换为 time.Time 对象。它支持多种语言和格式,非常适合处理用户输入的非结构化日期时间信息。

安装

go get -u github.com/olebedev/when

基本使用

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules/common"
	"github.com/olebedev/when/rules/en"
)

func main() {
	// 创建 when 解析器
	w := when.New(nil)
	
	// 添加英文规则
	w.Add(en.All...)
	w.Add(common.All...)
	
	// 解析自然语言日期时间
	text := "Meet me at 3pm tomorrow"
	r, err := w.Parse(text, time.Now())
	if err != nil {
		panic(err)
	}
	
	if r == nil {
		fmt.Println("No date/time found in text")
		return
	}
	
	fmt.Println("Matched text:", r.Text)           // "3pm tomorrow"
	fmt.Println("Parsed time:", r.Time)           // 具体的 time.Time 对象
	fmt.Println("Index in text:", r.Index)        // 匹配文本的起始位置
	fmt.Println("Source string:", text)           // 原始字符串
}

高级用法

1. 自定义解析规则

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules"
)

// 自定义规则:解析 "next week" 为下周
type NextWeek struct{}

func (n *NextWeek) Apply(text string, t time.Time, opts rules.Options) *rules.MatchResult {
	if text == "next week" {
		return &rules.MatchResult{
			Text: text,
			Time: t.AddDate(0, 0, 7),
			Index: 0,
		}
	}
	return nil
}

func main() {
	w := when.New(nil)
	w.Add(&NextWeek{})
	
	text := "Let's meet next week"
	r, _ := w.Parse(text, time.Now())
	
	fmt.Println("Parsed time:", r.Time) // 当前时间 + 7天
}

2. 多语言支持

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules/common"
	"github.com/olebedev/when/rules/ru" // 俄语规则
)

func main() {
	w := when.New(nil)
	w.Add(ru.All...)
	w.Add(common.All...)
	
	text := "встретимся через 2 дня" // 俄语"两天后见面"
	r, _ := w.Parse(text, time.Now())
	
	fmt.Println("Parsed time:", r.Time) // 当前时间 + 2天
}

3. 处理多个日期时间

package main

import (
	"fmt"
	"time"
	
	"github.com/olebedev/when"
	"github.com/olebedev/when/rules/common"
	"github.com/olebedev/when/rules/en"
)

func main() {
	w := when.New(nil)
	w.Add(en.All...)
	w.Add(common.All...)
	
	text := "The event starts at 3pm tomorrow and ends at 5pm the day after"
	base := time.Now()
	
	// 查找所有匹配
	var results []*rules.MatchResult
	for {
		r, err := w.Parse(text, base)
		if err != nil || r == nil {
			break
		}
		results = append(results, r)
		text = text[r.Index+len(r.Text):] // 继续解析剩余文本
	}
	
	for i, r := range results {
		fmt.Printf("Match %d: %q -> %v\n", i+1, r.Text, r.Time)
	}
}

常见用例

1. 解析相对时间

text := "in 2 hours"
r, _ := w.Parse(text, time.Now())
fmt.Println(r.Time) // 当前时间 + 2小时

2. 解析绝对时间

text := "January 15, 2023 at 3pm"
r, _ := w.Parse(text, time.Now())
fmt.Println(r.Time) // 2023-01-15 15:00:00 +0000 UTC

3. 解析模糊时间

text := "next Monday"
r, _ := w.Parse(text, time.Now())
fmt.Println(r.Time) // 下周一 00:00:00

性能优化

对于需要频繁解析的场景,可以重用 when 实例:

var parser *when.Parser

func init() {
	parser = when.New(nil)
	parser.Add(en.All...)
	parser.Add(common.All...)
}

func ParseDateTime(text string) (time.Time, error) {
	r, err := parser.Parse(text, time.Now())
	if err != nil || r == nil {
		return time.Time{}, fmt.Errorf("could not parse date/time")
	}
	return r.Time, nil
}

注意事项

  1. 解析器对输入文本的大小写不敏感
  2. 对于模糊匹配,结果可能不是用户预期的,需要适当验证
  3. 复杂的日期时间表达式可能需要自定义规则
  4. 不同语言规则可能需要单独添加

when 库为处理自然语言日期时间提供了强大而灵活的工具,特别适合聊天机器人、日历应用等需要处理用户自由输入日期时间的场景。

回到顶部