forked from couchbaselabs/gojsonsm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fastval_date.go
90 lines (83 loc) · 2.8 KB
/
fastval_date.go
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
package gojsonsm
import (
"fmt"
"regexp"
"time"
)
var iso8601Year *regexp.Regexp = regexp.MustCompile(`^(19|20)\d\d$`)
var iso8601YearAndMonth *regexp.Regexp = regexp.MustCompile(`^(19|20)\d\d[- /.](0[1-9]|1[012])$`)
var iso8601CompleteDate *regexp.Regexp = regexp.MustCompile(`^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$`)
// For parsing date
// Commonly used in couchbase demo and maybe other common use cases for parsing
// Format: "YYYY-MM-DD HH:MM:SS"
// Can easily convert to ISO 8601 internally
var cbSampleDateFormat *regexp.Regexp = regexp.MustCompile(`^((19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])) +(([0-1][0-9]|[2][0-3]):[0-5][0-9]:[0-5][0-9])$`)
func validTimeChecker(s string) bool {
_, err := time.Parse(time.RFC3339, s)
return err == nil || iso8601Year.MatchString(s) || iso8601YearAndMonth.MatchString(s) || iso8601CompleteDate.MatchString(s)
}
func isoToRfc(str string) string {
if iso8601Year.MatchString(str) {
str = fmt.Sprintf(`%s-01-01T00:00:00Z`, str)
} else if iso8601YearAndMonth.MatchString(str) {
str = fmt.Sprintf(`%s-01T00:00:00Z`, str)
} else if iso8601CompleteDate.MatchString(str) {
str = fmt.Sprintf(`%sT00:00:00Z`, str)
}
return str
}
func FastValDateFunc(val FastVal) FastVal {
switch val.Type() {
case TimeValue:
return val
case JsonStringValue:
fallthrough
case BinStringValue:
binVal, _ := val.ToBinString()
var str string
if iso8601Year.Match(binVal.sliceData) {
str = fmt.Sprintf(`%s-01-01T00:00:00Z`, binVal.sliceData)
} else if iso8601YearAndMonth.Match(binVal.sliceData) {
str = fmt.Sprintf(`%s-01T00:00:00Z`, binVal.sliceData)
} else if iso8601CompleteDate.Match(binVal.sliceData) {
str = fmt.Sprintf(`%sT00:00:00Z`, binVal.sliceData)
} else if cbSampleDateFormat.Match(binVal.sliceData) {
// len() call is very expensive. Use .Match() first then FindSubmatch
submatches := cbSampleDateFormat.FindSubmatch(binVal.sliceData)
if len(submatches) == 7 {
// Must be 7 submatches in the form:
// 0: 2019-01-01 23:59:59
// 1: 2019-01-01
// 2: 20
// 3: 01
// 4: 01
// 5: 23:59:59
// 6: 23
str = fmt.Sprintf(`%sT%sZ`, submatches[1], submatches[5])
}
} else {
str = fmt.Sprintf(`%s`, binVal.sliceData)
}
timeVal, err := time.Parse(time.RFC3339, str)
if err != nil {
return NewInvalidFastVal()
}
return NewTimeFastVal(&timeVal)
case StringValue:
str := isoToRfc(val.data.(string))
timeVal, err := time.Parse(time.RFC3339, str)
if err != nil {
return NewInvalidFastVal()
}
return NewTimeFastVal(&timeVal)
}
return NewInvalidFastVal()
}
func GetNewTimeFastVal(input string) (FastVal, error) {
str := isoToRfc(input)
if timeVal, err := time.Parse(time.RFC3339, str); err == nil {
return NewFastVal(&timeVal), nil
} else {
return NewInvalidFastVal(), err
}
}