-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.go
More file actions
128 lines (113 loc) · 3.45 KB
/
Copy pathparser.go
File metadata and controls
128 lines (113 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package chronos
import (
"fmt"
"time"
"github.com/gomooth/chronos/internal/parse"
)
// ParseOption 时间解析选项(通过 ParseWithXxx 函数设置)
type ParseOption struct {
fromStringOptions []func(*parse.FromStringOption)
fromNaturalLanguage struct {
supported bool
options []func(*parse.FromNaturalLanguageOption)
}
baseTime *time.Time
loc *time.Location
precision *Precision
}
// Parse 时间解析
func Parse[T TimeValue](v T, opts ...func(*ParseOption)) (*time.Time, error) {
cnf := new(ParseOption)
for _, opt := range opts {
opt(cnf)
}
now := time.Now()
if cnf.baseTime != nil && !cnf.baseTime.IsZero() {
now = *cnf.baseTime
}
if cnf.loc != nil {
now = now.In(cnf.loc)
}
switch val := any(v).(type) {
case time.Time:
return &val, nil
case *time.Time:
if val == nil {
return nil, fmt.Errorf("parse: nil *time.Time")
}
return val, nil
case int, int16, int32, int64, uint, uint16, uint32, uint64, uintptr:
var t time.Time
var err error
if cnf.precision != nil {
t, err = parse.FromUnixTimeWithPrecision(val, int(*cnf.precision))
} else {
t, err = parse.FromUnixTime(val)
}
if err != nil {
return nil, fmt.Errorf("parse: invalid unix time: %w", err)
}
if cnf.loc != nil {
t = t.In(cnf.loc)
}
return &t, nil
default:
str, ok := val.(string)
if !ok {
return nil, fmt.Errorf("parse: unsupported type %T", v)
}
loc := now.Location()
if cnf.loc != nil {
loc = cnf.loc
}
// 特殊表达式(now/today/yesterday/tomorrow 及中文等价词),无需 NL 标志
if t, matched := parse.FromSpecialExpression(str, now, loc); matched {
return &t, nil
}
// 尝试解析字符串为时间
parsed, err := parse.FromStringFormat(str, cnf.fromStringOptions...)
if err != nil {
if !cnf.fromNaturalLanguage.supported {
return nil, err
}
// 尝试解析自然语言
parsed, err = parse.FromNaturalLanguage(str, now, cnf.fromNaturalLanguage.options...)
if err != nil {
return nil, err
}
}
return &parsed, nil
}
}
// ParseWithLayout 指定时间解析的自定义格式
func ParseWithLayout(layout string, others ...string) func(*ParseOption) {
return func(p *ParseOption) {
p.fromStringOptions = append(p.fromStringOptions, parse.WithFromStringLayout(layout))
for _, other := range others {
p.fromStringOptions = append(p.fromStringOptions, parse.WithFromStringLayout(other))
}
}
}
// ParseWithLocation 指定时间解析的时区
// 对字符串和 Unix 时间戳输入生效;直接传入 time.Time 或 *time.Time 时不生效(保留原时区)
func ParseWithLocation(loc *time.Location) func(*ParseOption) {
return func(p *ParseOption) {
p.loc = loc
p.fromStringOptions = append(p.fromStringOptions, parse.WithFromStringLocation(loc))
p.fromNaturalLanguage.options = append(p.fromNaturalLanguage.options, parse.WithFromNaturalLanguageLocation(loc))
}
}
// ParseWithBaseTime 指定自然语言解析的基准时间
// 影响范围:"now"/"yesterday"/"tomorrow" 特殊表达式、自然语言解析
// 不影响:Unix 时间戳解析、字符串格式化解析(这两类输入本身已包含完整时间信息)
func ParseWithBaseTime(base time.Time) func(*ParseOption) {
return func(p *ParseOption) {
p.baseTime = &base
}
}
// ParseWithNaturalLanguage 指定时间解析是否支持自然语言
func ParseWithNaturalLanguage(supported bool) func(*ParseOption) {
return func(p *ParseOption) {
p.fromNaturalLanguage.supported = supported
}
}