-
Notifications
You must be signed in to change notification settings - Fork 111
/
timeutil.go
152 lines (133 loc) · 4.24 KB
/
timeutil.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
147
148
149
150
151
152
package queries
import (
"fmt"
"time"
"github.com/rilldata/rill/proto/gen/rill/runtime/v1"
"github.com/rilldata/rill/runtime/pkg/duration"
"github.com/rilldata/rill/runtime/pkg/timeutil"
)
func convTimeGrain(tg runtimev1.TimeGrain) timeutil.TimeGrain {
switch tg {
case runtimev1.TimeGrain_TIME_GRAIN_MILLISECOND:
return timeutil.TimeGrainMillisecond
case runtimev1.TimeGrain_TIME_GRAIN_SECOND:
return timeutil.TimeGrainSecond
case runtimev1.TimeGrain_TIME_GRAIN_MINUTE:
return timeutil.TimeGrainMinute
case runtimev1.TimeGrain_TIME_GRAIN_HOUR:
return timeutil.TimeGrainHour
case runtimev1.TimeGrain_TIME_GRAIN_DAY:
return timeutil.TimeGrainDay
case runtimev1.TimeGrain_TIME_GRAIN_WEEK:
return timeutil.TimeGrainWeek
case runtimev1.TimeGrain_TIME_GRAIN_MONTH:
return timeutil.TimeGrainMonth
case runtimev1.TimeGrain_TIME_GRAIN_QUARTER:
return timeutil.TimeGrainQuarter
case runtimev1.TimeGrain_TIME_GRAIN_YEAR:
return timeutil.TimeGrainYear
}
return timeutil.TimeGrainUnspecified
}
func timeGrainToDuration(tg runtimev1.TimeGrain) duration.Duration {
switch tg {
// not supported
// case runtimev1.TimeGrain_TIME_GRAIN_MILLISECOND:
case runtimev1.TimeGrain_TIME_GRAIN_SECOND:
return duration.StandardDuration{Second: 1}
case runtimev1.TimeGrain_TIME_GRAIN_MINUTE:
return duration.StandardDuration{Minute: 1}
case runtimev1.TimeGrain_TIME_GRAIN_HOUR:
return duration.StandardDuration{Hour: 1}
case runtimev1.TimeGrain_TIME_GRAIN_DAY:
return duration.StandardDuration{Day: 1}
case runtimev1.TimeGrain_TIME_GRAIN_WEEK:
return duration.StandardDuration{Week: 1}
case runtimev1.TimeGrain_TIME_GRAIN_MONTH:
return duration.StandardDuration{Month: 1}
case runtimev1.TimeGrain_TIME_GRAIN_QUARTER:
return duration.StandardDuration{Month: 3}
case runtimev1.TimeGrain_TIME_GRAIN_YEAR:
return duration.StandardDuration{Year: 1}
}
return duration.InfDuration{}
}
// func ResolveToTime(t *timestamppb.Timestamp, timeZone string) (time.Time, error) {
// if timeZone != "" {
// var err error
// tz, err := time.LoadLocation(timeZone)
// if err != nil {
// return time.Time{}, fmt.Errorf("invalid time_range.time_zone %q: %w", timeZone, err)
// }
// return t.AsTime().In(tz), nil
// } else {
// return t.AsTime(), nil
// }
// }
func ResolveTimeRange(tr *runtimev1.TimeRange, mv *runtimev1.MetricsViewSpec) (time.Time, time.Time, error) {
tz := time.UTC
if tr.TimeZone != "" {
var err error
tz, err = time.LoadLocation(tr.TimeZone)
if err != nil {
return time.Time{}, time.Time{}, fmt.Errorf("invalid time_range.time_zone %q: %w", tr.TimeZone, err)
}
}
var start, end time.Time
if tr.Start != nil {
start = tr.Start.AsTime().In(tz)
}
if tr.End != nil {
end = tr.End.AsTime().In(tz)
}
isISO := false
if tr.IsoDuration != "" {
if !start.IsZero() && !end.IsZero() {
return time.Time{}, time.Time{}, fmt.Errorf("only two of time_range.{start,end,iso_duration} can be specified")
}
d, err := duration.ParseISO8601(tr.IsoDuration)
if err != nil {
return time.Time{}, time.Time{}, fmt.Errorf("invalid iso_duration %q: %w", tr.IsoDuration, err)
}
if !start.IsZero() {
end = d.Add(start)
} else if !end.IsZero() {
start = d.Sub(end)
} else {
return time.Time{}, time.Time{}, fmt.Errorf("one of time_range.{start,end} must be specified with time_range.iso_duration")
}
isISO = true
}
if tr.IsoOffset != "" {
d, err := duration.ParseISO8601(tr.IsoOffset)
if err != nil {
return time.Time{}, time.Time{}, fmt.Errorf("invalid iso_offset %q: %w", tr.IsoOffset, err)
}
if !start.IsZero() {
start = d.Sub(start)
}
if !end.IsZero() {
end = d.Sub(end)
}
isISO = true
}
// Only modify the start and end if ISO duration or offset was sent.
// This is to maintain backwards compatibility for calls from the UI.
if isISO {
fdow := int(mv.FirstDayOfWeek)
if mv.FirstDayOfWeek > 7 || mv.FirstDayOfWeek <= 0 {
fdow = 1
}
fmoy := int(mv.FirstMonthOfYear)
if mv.FirstMonthOfYear > 12 || mv.FirstMonthOfYear <= 0 {
fmoy = 1
}
if !start.IsZero() {
start = timeutil.TruncateTime(start, convTimeGrain(tr.RoundToGrain), tz, fdow, fmoy)
}
if !end.IsZero() {
end = timeutil.TruncateTime(end, convTimeGrain(tr.RoundToGrain), tz, fdow, fmoy)
}
}
return start, end, nil
}