mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
157 lines
3.6 KiB
Go
157 lines
3.6 KiB
Go
package pilosa
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// TimeQuantum represents a time granularity for time-based bitmap ids.
|
|
type TimeQuantum uint
|
|
|
|
// ParseTimeQuantum parses s into a quantum.
|
|
func ParseTimeQuantum(s string) (TimeQuantum, error) {
|
|
switch strings.ToUpper(s) {
|
|
case "Y":
|
|
return Y, nil
|
|
case "M":
|
|
return YM, nil
|
|
case "D":
|
|
return YMD, nil
|
|
case "H":
|
|
return YMDH, nil
|
|
default:
|
|
return 0, errors.New("invalid quantum")
|
|
}
|
|
}
|
|
|
|
// String returns the string representation of the quantum.
|
|
func (q TimeQuantum) String() string {
|
|
switch q {
|
|
case Y:
|
|
return "Y"
|
|
case YM:
|
|
return "M"
|
|
case YMD:
|
|
return "D"
|
|
case YMDH:
|
|
return "H"
|
|
default:
|
|
return "Y"
|
|
}
|
|
}
|
|
|
|
const (
|
|
Y TimeQuantum = 3
|
|
YM TimeQuantum = 2
|
|
YMD TimeQuantum = 1
|
|
YMDH TimeQuantum = 0
|
|
)
|
|
|
|
// TimeID returns a packed time identifier from a year/month/day/hour & tile.
|
|
func TimeID(q TimeQuantum, year uint, month uint, day uint, hour uint, tileID uint64) uint64 {
|
|
v := uint64((uint(q) << 30) | ((year - 1970) << 23) | (month << 19) | (day << 14) | (hour << 9))
|
|
return (v << 32) | tileID
|
|
}
|
|
|
|
// TimeIDsFromRange returns timestamp bitmap ids within a time range.
|
|
func TimeIDsFromRange(start, end time.Time, tileID uint64) []uint64 {
|
|
t := start
|
|
|
|
var results []uint64
|
|
for t.Before(end) {
|
|
if !nextDay(t, end) {
|
|
break
|
|
}
|
|
if t.Hour() == 0 {
|
|
if !nextMonth(t, end) {
|
|
break
|
|
}
|
|
|
|
if t.Day() == 1 {
|
|
if !nextYear(t, end) {
|
|
break
|
|
}
|
|
|
|
if t.Month() == 1 {
|
|
break
|
|
}
|
|
|
|
results = append(results, TimeID(YM, uint(t.Year()), uint(t.Month()), 0, 0, tileID))
|
|
t = t.AddDate(0, 1, 0)
|
|
} else {
|
|
results = append(results, TimeID(YMD, uint(t.Year()), uint(t.Month()), uint(t.Day()), 0, tileID))
|
|
t = t.AddDate(0, 0, 1)
|
|
}
|
|
} else {
|
|
results = append(results, TimeID(YMDH, uint(t.Year()), uint(t.Month()), uint(t.Day()), uint(t.Hour()), tileID))
|
|
t = t.Add(time.Hour)
|
|
}
|
|
}
|
|
|
|
for t.Before(end) {
|
|
if nextYear(t, end) {
|
|
results = append(results, TimeID(Y, uint(t.Year()), 0, 0, 0, tileID))
|
|
t = t.AddDate(1, 0, 0)
|
|
} else if nextMonth(t, end) {
|
|
results = append(results, TimeID(YM, uint(t.Year()), uint(t.Month()), 0, 0, tileID))
|
|
t = t.AddDate(0, 1, 0)
|
|
} else if nextDay(t, end) {
|
|
results = append(results, TimeID(YMD, uint(t.Year()), uint(t.Month()), uint(t.Day()), 0, tileID))
|
|
t = t.AddDate(0, 0, 1)
|
|
} else {
|
|
results = append(results, TimeID(YMDH, uint(t.Year()), uint(t.Month()), uint(t.Day()), uint(t.Hour()), tileID))
|
|
t = t.Add(time.Hour)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
func nextYear(start time.Time, end time.Time) bool {
|
|
next := start.AddDate(1, 0, 0)
|
|
if next.Year() == end.Year() {
|
|
return true
|
|
}
|
|
return end.After(next)
|
|
}
|
|
|
|
func nextMonth(start time.Time, end time.Time) bool {
|
|
next := start.AddDate(0, 1, 0)
|
|
y1, m1, _ := next.Date()
|
|
y2, m2, _ := end.Date()
|
|
if (y1 == y2) && (m1 == m2) {
|
|
return true
|
|
}
|
|
return end.After(next)
|
|
}
|
|
|
|
func nextDay(start time.Time, end time.Time) bool {
|
|
next := start.AddDate(0, 0, 1)
|
|
y1, m1, d1 := next.Date()
|
|
y2, m2, d2 := end.Date()
|
|
if (y1 == y2) && (m1 == m2) && (d1 == d2) {
|
|
return true
|
|
}
|
|
return end.After(next)
|
|
}
|
|
|
|
// TimeIDsFromQuantum returns a list of time identifiers for a single quantum.
|
|
func TimeIDsFromQuantum(q TimeQuantum, t time.Time, tileID uint64) []uint64 {
|
|
y, m, d, h := uint(t.Year()), uint(t.Month()), uint(t.Day()), uint(t.Hour())
|
|
|
|
v := make([]uint64, 0, 4)
|
|
if q <= Y {
|
|
v = append(v, TimeID(Y, y, 0, 0, 0, tileID))
|
|
}
|
|
if q <= YM {
|
|
v = append(v, TimeID(YM, y, m, 0, 0, tileID))
|
|
}
|
|
if q <= YMD {
|
|
v = append(v, TimeID(YMD, y, m, d, 0, tileID))
|
|
}
|
|
if q <= YMDH {
|
|
v = append(v, TimeID(YMDH, y, m, d, h, tileID))
|
|
}
|
|
return v
|
|
}
|