-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdate.go
117 lines (104 loc) · 2.39 KB
/
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
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
package coin
import (
"fmt"
"strconv"
"time"
"github.com/mkobetic/coin/rex"
)
func init() {
var m time.Month
Year, m, Day = time.Now().Date()
Month = int(m)
}
// Cache today's values, so that we can spoof today for testing
var Year, Month, Day int
type Date struct {
time.Time
}
func (d *Date) String() string {
return d.Format(DateFormat)
}
func (d *Date) Set(s string) (err error) {
match := DateREX.Match([]byte(s))
if match == nil {
return fmt.Errorf("invalid date: %s", s)
}
d.Time, err = parseDate(match, 0)
return err
}
var DateFormat = "2006/01/02"
var MonthFormat = "2006/01"
var YearFormat = "2006"
var ymd = rex.MustCompile(`` +
`((?P<ymd>((?P<ymdy>\d\d(\d\d)?)/)?(?P<ymdm>\d{1,2})/(?P<ymdd>\d{1,2}))|` +
`(?P<ym>(?P<ymy>\d{4})(/(?P<ymm>\d{1,2}))?))`)
var offset = rex.MustCompile(`(?P<offset>[+-]\d+[d|w|m|y])`)
var DateREX = rex.MustCompile(`(?P<date>%s?%s?)`, ymd, offset)
func mustParseDate(match map[string]string, idx int) time.Time {
d, err := parseDate(match, idx)
if err != nil {
panic(err)
}
return d
}
func MustParseDate(s string) time.Time {
match := DateREX.Match([]byte(s))
return mustParseDate(match, 0)
}
func parseDate(match map[string]string, idx int) (t time.Time, err error) {
if idx > 0 {
return t, fmt.Errorf("multiple date fields not implemented!")
}
// Set date to today
y, m, d := Year, Month, Day
offset := match["offset"]
if match["ymd"] != "" {
d, _ = strconv.Atoi(match["ymdd"])
mm, _ := strconv.Atoi(match["ymdm"])
if yy := match["ymdy"]; yy != "" {
yyy, _ := strconv.Atoi(yy)
if yyy < 100 {
yyy = y/1000*1000 + yyy
if yyy < y && y-yyy > 50 {
yyy += 100
} else if yyy > y && yyy-y > 50 {
yyy -= 100
}
y = yyy
} else {
y = yyy
}
} else {
if mm < m && m-mm > 6 {
y += 1
} else if m < mm && mm-m > 6 {
y -= 1
}
}
m = mm
} else if match["ym"] != "" {
d, m = 1, 1
y, _ = strconv.Atoi(match["ymy"])
if mm := match["ymm"]; mm != "" {
m, _ = strconv.Atoi(mm)
}
} else if offset == "" {
return t, fmt.Errorf("no match for date: %v", match)
}
t = time.Date(y, time.Month(m), d, 12, 0, 0, 0, time.UTC)
if offset != "" {
e := len(offset) - 1
o, _ := strconv.Atoi(offset[:e])
switch offset[e] {
case 'd':
t = t.AddDate(0, 0, o)
case 'w':
t = t.AddDate(0, 0, o*7)
case 'm':
t = t.AddDate(0, o, 0)
case 'y':
t = t.AddDate(o, 0, 0)
}
}
return t, nil
}