1package now
2
3import (
4	"errors"
5	"regexp"
6	"time"
7)
8
9func (now *Now) BeginningOfMinute() time.Time {
10	return now.Truncate(time.Minute)
11}
12
13func (now *Now) BeginningOfHour() time.Time {
14	return now.Truncate(time.Hour)
15}
16
17func (now *Now) BeginningOfDay() time.Time {
18	d := time.Duration(-now.Hour()) * time.Hour
19	return now.BeginningOfHour().Add(d)
20}
21
22func (now *Now) BeginningOfWeek() time.Time {
23	t := now.BeginningOfDay()
24	weekday := int(t.Weekday())
25	if FirstDayMonday {
26		if weekday == 0 {
27			weekday = 7
28		}
29		weekday = weekday - 1
30	}
31
32	d := time.Duration(-weekday) * 24 * time.Hour
33	return t.Add(d)
34}
35
36func (now *Now) BeginningOfMonth() time.Time {
37	t := now.BeginningOfDay()
38	d := time.Duration(-int(t.Day())+1) * 24 * time.Hour
39	return t.Add(d)
40}
41
42func (now *Now) BeginningOfQuarter() time.Time {
43	month := now.BeginningOfMonth()
44	offset := (int(month.Month()) - 1) % 3
45	return month.AddDate(0, -offset, 0)
46}
47
48func (now *Now) BeginningOfYear() time.Time {
49	t := now.BeginningOfDay()
50	d := time.Duration(-int(t.YearDay())+1) * 24 * time.Hour
51	return t.Truncate(time.Hour).Add(d)
52}
53
54func (now *Now) EndOfMinute() time.Time {
55	return now.BeginningOfMinute().Add(time.Minute - time.Nanosecond)
56}
57
58func (now *Now) EndOfHour() time.Time {
59	return now.BeginningOfHour().Add(time.Hour - time.Nanosecond)
60}
61
62func (now *Now) EndOfDay() time.Time {
63	return now.BeginningOfDay().Add(24*time.Hour - time.Nanosecond)
64}
65
66func (now *Now) EndOfWeek() time.Time {
67	return now.BeginningOfWeek().AddDate(0, 0, 7).Add(-time.Nanosecond)
68}
69
70func (now *Now) EndOfMonth() time.Time {
71	return now.BeginningOfMonth().AddDate(0, 1, 0).Add(-time.Nanosecond)
72}
73
74func (now *Now) EndOfQuarter() time.Time {
75	return now.BeginningOfQuarter().AddDate(0, 3, 0).Add(-time.Nanosecond)
76}
77
78func (now *Now) EndOfYear() time.Time {
79	return now.BeginningOfYear().AddDate(1, 0, 0).Add(-time.Nanosecond)
80}
81
82func (now *Now) Monday() time.Time {
83	t := now.BeginningOfDay()
84	weekday := int(t.Weekday())
85	if weekday == 0 {
86		weekday = 7
87	}
88	d := time.Duration(-weekday+1) * 24 * time.Hour
89	return t.Truncate(time.Hour).Add(d)
90}
91
92func (now *Now) Sunday() time.Time {
93	t := now.BeginningOfDay()
94	weekday := int(t.Weekday())
95	if weekday == 0 {
96		return t
97	} else {
98		d := time.Duration(7-weekday) * 24 * time.Hour
99		return t.Truncate(time.Hour).Add(d)
100	}
101}
102
103func (now *Now) EndOfSunday() time.Time {
104	return now.Sunday().Add(24*time.Hour - time.Nanosecond)
105}
106
107func parseWithFormat(str string) (t time.Time, err error) {
108	for _, format := range TimeFormats {
109		t, err = time.Parse(format, str)
110		if err == nil {
111			return
112		}
113	}
114	err = errors.New("Can't parse string as time: " + str)
115	return
116}
117
118func (now *Now) Parse(strs ...string) (t time.Time, err error) {
119	var setCurrentTime bool
120	parseTime := []int{}
121	currentTime := []int{now.Second(), now.Minute(), now.Hour(), now.Day(), int(now.Month()), now.Year()}
122	currentLocation := now.Location()
123
124	for _, str := range strs {
125		onlyTime := regexp.MustCompile(`^\s*\d+(:\d+)*\s*$`).MatchString(str) // match 15:04:05, 15
126
127		t, err = parseWithFormat(str)
128		location := t.Location()
129		if location.String() == "UTC" {
130			location = currentLocation
131		}
132
133		if err == nil {
134			parseTime = []int{t.Second(), t.Minute(), t.Hour(), t.Day(), int(t.Month()), t.Year()}
135			onlyTime = onlyTime && (parseTime[3] == 1) && (parseTime[4] == 1)
136
137			for i, v := range parseTime {
138				// Don't reset hour, minute, second if it is a time only string
139				if onlyTime && i <= 2 {
140					continue
141				}
142
143				// Fill up missed information with current time
144				if v == 0 {
145					if setCurrentTime {
146						parseTime[i] = currentTime[i]
147					}
148				} else {
149					setCurrentTime = true
150				}
151
152				// Default day and month is 1, fill up it if missing it
153				if onlyTime {
154					if i == 3 || i == 4 {
155						parseTime[i] = currentTime[i]
156						continue
157					}
158				}
159			}
160		}
161
162		if len(parseTime) > 0 {
163			t = time.Date(parseTime[5], time.Month(parseTime[4]), parseTime[3], parseTime[2], parseTime[1], parseTime[0], 0, location)
164			currentTime = []int{t.Second(), t.Minute(), t.Hour(), t.Day(), int(t.Month()), t.Year()}
165		}
166	}
167	return
168}
169
170func (now *Now) MustParse(strs ...string) (t time.Time) {
171	t, err := now.Parse(strs...)
172	if err != nil {
173		panic(err)
174	}
175	return t
176}
177
178func (now *Now) Between(time1, time2 string) bool {
179	restime := now.MustParse(time1)
180	restime2 := now.MustParse(time2)
181	return now.After(restime) && now.Before(restime2)
182}
183