/
units.go
146 lines (123 loc) · 2.79 KB
/
units.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package period
import (
"errors"
"time"
)
var (
ErrEmptyUnitModifier = errors.New("unit modifier is empty")
ErrInvalidUnit = errors.New("invalid unit")
ErrMissingUnit = errors.New("missing unit")
ErrMissingUnitModifier = errors.New("unit modifier is missing")
ErrUnexpectedUnit = errors.New("unexpected unit")
ErrUnitModifierIsNotUnique = errors.New("unit modifier is not unique")
)
type Unit int
const (
UnitUnknown Unit = iota
UnitYear
UnitMonth
UnitDay
UnitHour
UnitMinute
UnitSecond
UnitMillisecond
UnitMicrosecond
UnitNanosecond
)
const (
validUnitsQuantity = 9
)
// Units table for custom parsing and converting to string.
//
// Must contains all Unit constants (except UnitUnknown) and
// at least one modifier for each unit of measure.
// First modifier for unit is a default modifier that used when converting to string.
//
// Default units:
//
// - y - years;
// - mo - months;
// - d - days;
// - h - hours;
// - m - minutes;
// - s - seconds;
// - ms - milliseconds;
// - us, µs - microseconds;
// - ns - nanoseconds.
type UnitsTable map[Unit][]string
// Validates units table.
func IsValidUnitsTable(units UnitsTable) error {
unitsQuantity := 0
uniqueModifiers := make(map[string]struct{}, len(units))
for unit, modifiers := range units {
if err := isValidUnit(unit); err != nil {
return err
}
unitsQuantity++
if err := isValidModifiers(modifiers, uniqueModifiers); err != nil {
return err
}
}
if unitsQuantity != validUnitsQuantity {
return ErrMissingUnit
}
return nil
}
func isValidModifiers(modifiers []string, uniqueModifiers map[string]struct{}) error {
if len(modifiers) == 0 {
return ErrMissingUnitModifier
}
for _, modifier := range modifiers {
if len(modifier) == 0 {
return ErrEmptyUnitModifier
}
if _, exists := uniqueModifiers[modifier]; exists {
return ErrUnitModifierIsNotUnique
}
uniqueModifiers[modifier] = struct{}{}
}
return nil
}
func isValidUnit(unit Unit) error {
switch unit {
case UnitYear:
case UnitMonth:
case UnitDay:
case UnitHour:
case UnitMinute:
case UnitSecond:
case UnitMillisecond:
case UnitMicrosecond:
case UnitNanosecond:
default:
return ErrInvalidUnit
}
return nil
}
func isYMDUnit(unit Unit) bool {
switch unit {
case UnitYear:
case UnitMonth:
case UnitDay:
default:
return false
}
return true
}
func getDurationDimension(unit Unit) (time.Duration, error) {
switch unit {
case UnitHour:
return time.Hour, nil
case UnitMinute:
return time.Minute, nil
case UnitSecond:
return time.Second, nil
case UnitMillisecond:
return time.Millisecond, nil
case UnitMicrosecond:
return time.Microsecond, nil
case UnitNanosecond:
return time.Nanosecond, nil
}
return 0, ErrUnexpectedUnit
}