-
Notifications
You must be signed in to change notification settings - Fork 1
/
period.go
115 lines (96 loc) · 3.08 KB
/
period.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
package time
import (
"errors"
)
// Period represents a set of days between two dates (inclusive)
type Period struct {
from LocalDate
to LocalDate
}
// ErrPeriodInvalidFromAfterTo is returned when Period creating is called
// with invalid parameters: from > to
var ErrPeriodInvalidFromAfterTo = errors.New(`Invalid time period - "from" is after "to"`)
// ErrPeriodInvalidParamNull is returned when Period creating is called
// with invalid parameters: from or to is NullLocalDate
var ErrPeriodInvalidParamNull = errors.New(`Invalid time period - date is null`)
// NewPeriod creates Period that represents a set of days between two dates: "from" (inclusive) and "to" (inclusive)
func NewPeriod(from LocalDate, to LocalDate) (Period, error) {
if from.IsNull() || to.IsNull() {
return Period{from: NullLocalDate, to: NullLocalDate}, ErrPeriodInvalidParamNull
}
if from.After(to) {
return Period{from: NullLocalDate, to: NullLocalDate}, ErrPeriodInvalidFromAfterTo
}
return Period{from: from, to: to}, nil
}
// NewOneDayPeriod creates Period that represents a single day
func NewOneDayPeriod(date LocalDate) (Period, error) {
return NewPeriod(date, date)
}
// NewOpenPeriodFrom creates Period that represents a set of days between "from" (inclusive) and eternity
func NewOpenPeriodFrom(from LocalDate) (Period, error) {
if from.IsNull() {
return Period{from: NullLocalDate, to: NullLocalDate}, ErrPeriodInvalidParamNull
}
return Period{from: from, to: NullLocalDate}, nil
}
func MustNewOpenPeriodFrom(from LocalDate) Period {
period, err := NewOpenPeriodFrom(from)
if err != nil {
panic(err)
}
return period
}
func MustNewPeriod(from LocalDate, to LocalDate) Period {
period, err := NewPeriod(from, to)
if err != nil {
panic(err)
}
return period
}
func MustNewOneDayPeriod(date LocalDate) Period {
return MustNewPeriod(date, date)
}
// Days returns a slice of all days in a period in order
func (p Period) Days() []LocalDate {
var days []LocalDate
for current := p.from; current.BeforeOrEqual(p.to); current = current.Next() {
days = append(days, current)
}
return days
}
// Contains tells if period contains given date
func (p Period) Contains(date LocalDate) bool {
return p.from.BeforeOrEqual(date) && (date.BeforeOrEqual(p.to) || p.to.IsNull())
}
// From returns first day of a period
func (p Period) From() LocalDate {
return p.from
}
// To returns last day of a period
func (p Period) To() LocalDate {
return p.to
}
// NullableTo returns last day of a period or null
func (p Period) NullableTo() NullableLocalDate {
if p.to.IsNull() {
return NullableLocalDate{}
} else {
return NullableLocalDate{Date: p.to, Valid: true}
}
}
func (p Period) String() string {
if p.to == NullLocalDate {
return "[" + p.from.t.Format(LocalDateFormat) + " - indefinitely]"
}
return "[" + p.from.t.Format(LocalDateFormat) + " - " + p.to.t.Format(LocalDateFormat) + "]"
}
func (p Period) IsOpen() bool {
return p.to.IsNull()
}
func (p Period) ToDateTimeSpan() DateTimeSpan {
if p.IsOpen() {
return MustNewOpenDateTimeSpanFrom(p.from.Start())
}
return NewDateTimeSpan(p.from.Start(), p.to.End())
}