github.com/m3db/m3@v1.5.0/src/query/functions/linear/datetime.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package linear 22 23 import ( 24 "fmt" 25 "math" 26 "time" 27 28 "github.com/m3db/m3/src/query/block" 29 "github.com/m3db/m3/src/query/functions/lazy" 30 "github.com/m3db/m3/src/query/parser" 31 ) 32 33 const ( 34 // DayOfMonthType returns the day of the month for each of the given times 35 // in UTC. 36 // Returned values are from 1 to 31. 37 DayOfMonthType = "day_of_month" 38 39 // DayOfWeekType returns the day of the week for each of the given times 40 // in UTC. 41 // Returned values are from 0 to 6, where 0 means Sunday etc. 42 DayOfWeekType = "day_of_week" 43 44 // DaysInMonthType returns number of days in the month for each of the given 45 // times in UTC. 46 // Returned values are from 28 to 31. 47 DaysInMonthType = "days_in_month" 48 49 // HourType returns the hour of the day for each of the given times in UTC. 50 // Returned values are from 0 to 23. 51 HourType = "hour" 52 53 // MinuteType returns the minute of the hour for each of the given times 54 // in UTC. 55 // Returned values are from 0 to 59. 56 MinuteType = "minute" 57 58 // MonthType returns the month of the year for each of the given times in UTC. 59 // Returned values are from 1 to 12, where 1 means January etc. 60 MonthType = "month" 61 62 // YearType returns the year for each of the given times in UTC. 63 YearType = "year" 64 ) 65 66 type timeFn func(time.Time) float64 67 68 var ( 69 datetimeFuncs = map[string]timeFn{ 70 DayOfMonthType: func(t time.Time) float64 { return float64(t.Day()) }, 71 DayOfWeekType: func(t time.Time) float64 { return float64(t.Weekday()) }, 72 DaysInMonthType: func(t time.Time) float64 { 73 return float64(32 - time.Date(t.Year(), t.Month(), 74 32, 0, 0, 0, 0, time.UTC).Day()) 75 }, 76 HourType: func(t time.Time) float64 { return float64(t.Hour()) }, 77 MinuteType: func(t time.Time) float64 { return float64(t.Minute()) }, 78 MonthType: func(t time.Time) float64 { return float64(t.Month()) }, 79 YearType: func(t time.Time) float64 { return float64(t.Year()) }, 80 } 81 ) 82 83 func buildTransform(fn timeFn, usingSeries bool) block.ValueTransform { 84 if !usingSeries { 85 return func(v float64) float64 { 86 return fn(time.Now()) 87 } 88 } 89 90 return func(v float64) float64 { 91 if math.IsNaN(v) { 92 return v 93 } 94 95 t := time.Unix(int64(v), 0).UTC() 96 return fn(t) 97 } 98 } 99 100 // NewDateOp creates a new date op based on the type. 101 func NewDateOp(opType string, usingSeries bool) (parser.Params, error) { 102 if dateFn, ok := datetimeFuncs[opType]; ok { 103 fn := buildTransform(dateFn, usingSeries) 104 lazyOpts := block.NewLazyOptions().SetValueTransform(fn) 105 return lazy.NewLazyOp(opType, lazyOpts) 106 } 107 108 return nil, fmt.Errorf("unknown date type: %s", opType) 109 }