mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-03 17:29:22 -05:00
0f2b2b9a94
* enhancement: add more kql spec tests and simplify ast normalization * enhancement: kql parser error if query starts with AND * enhancement: add kql docs and support for date and time only dateTimeRestriction queries * enhancement: add the ability to decide how kql nodes get connected connecting nodes (with edges) seem straight forward when not using group, the default connection for nodes with the same node is always OR. THis only applies for first level nodes, for grouped nodes it is defined differently. The KQL docs are saying, nodes inside a grouped node, with the same key are connected by a AND edge. * enhancement: explicit error handling for falsy group nodes and queries with leading binary operator * enhancement: use optimized grammar for kql parser and toolify pigeon * enhancement: simplify error handling * fix: kql implicit 'AND' and 'OR' follows the ms html spec instead of the pdf spec * enhancement: add support for natural language kql date queries * enhancement: structure kql parser tests into logical clusters * fix: time-range error naming
246 lines
6.3 KiB
Go
246 lines
6.3 KiB
Go
package now
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"time"
|
|
)
|
|
|
|
// BeginningOfMinute beginning of minute
|
|
func (now *Now) BeginningOfMinute() time.Time {
|
|
return now.Truncate(time.Minute)
|
|
}
|
|
|
|
// BeginningOfHour beginning of hour
|
|
func (now *Now) BeginningOfHour() time.Time {
|
|
y, m, d := now.Date()
|
|
return time.Date(y, m, d, now.Time.Hour(), 0, 0, 0, now.Time.Location())
|
|
}
|
|
|
|
// BeginningOfDay beginning of day
|
|
func (now *Now) BeginningOfDay() time.Time {
|
|
y, m, d := now.Date()
|
|
return time.Date(y, m, d, 0, 0, 0, 0, now.Time.Location())
|
|
}
|
|
|
|
// BeginningOfWeek beginning of week
|
|
func (now *Now) BeginningOfWeek() time.Time {
|
|
t := now.BeginningOfDay()
|
|
weekday := int(t.Weekday())
|
|
|
|
if now.WeekStartDay != time.Sunday {
|
|
weekStartDayInt := int(now.WeekStartDay)
|
|
|
|
if weekday < weekStartDayInt {
|
|
weekday = weekday + 7 - weekStartDayInt
|
|
} else {
|
|
weekday = weekday - weekStartDayInt
|
|
}
|
|
}
|
|
return t.AddDate(0, 0, -weekday)
|
|
}
|
|
|
|
// BeginningOfMonth beginning of month
|
|
func (now *Now) BeginningOfMonth() time.Time {
|
|
y, m, _ := now.Date()
|
|
return time.Date(y, m, 1, 0, 0, 0, 0, now.Location())
|
|
}
|
|
|
|
// BeginningOfQuarter beginning of quarter
|
|
func (now *Now) BeginningOfQuarter() time.Time {
|
|
month := now.BeginningOfMonth()
|
|
offset := (int(month.Month()) - 1) % 3
|
|
return month.AddDate(0, -offset, 0)
|
|
}
|
|
|
|
// BeginningOfHalf beginning of half year
|
|
func (now *Now) BeginningOfHalf() time.Time {
|
|
month := now.BeginningOfMonth()
|
|
offset := (int(month.Month()) - 1) % 6
|
|
return month.AddDate(0, -offset, 0)
|
|
}
|
|
|
|
// BeginningOfYear BeginningOfYear beginning of year
|
|
func (now *Now) BeginningOfYear() time.Time {
|
|
y, _, _ := now.Date()
|
|
return time.Date(y, time.January, 1, 0, 0, 0, 0, now.Location())
|
|
}
|
|
|
|
// EndOfMinute end of minute
|
|
func (now *Now) EndOfMinute() time.Time {
|
|
return now.BeginningOfMinute().Add(time.Minute - time.Nanosecond)
|
|
}
|
|
|
|
// EndOfHour end of hour
|
|
func (now *Now) EndOfHour() time.Time {
|
|
return now.BeginningOfHour().Add(time.Hour - time.Nanosecond)
|
|
}
|
|
|
|
// EndOfDay end of day
|
|
func (now *Now) EndOfDay() time.Time {
|
|
y, m, d := now.Date()
|
|
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), now.Location())
|
|
}
|
|
|
|
// EndOfWeek end of week
|
|
func (now *Now) EndOfWeek() time.Time {
|
|
return now.BeginningOfWeek().AddDate(0, 0, 7).Add(-time.Nanosecond)
|
|
}
|
|
|
|
// EndOfMonth end of month
|
|
func (now *Now) EndOfMonth() time.Time {
|
|
return now.BeginningOfMonth().AddDate(0, 1, 0).Add(-time.Nanosecond)
|
|
}
|
|
|
|
// EndOfQuarter end of quarter
|
|
func (now *Now) EndOfQuarter() time.Time {
|
|
return now.BeginningOfQuarter().AddDate(0, 3, 0).Add(-time.Nanosecond)
|
|
}
|
|
|
|
// EndOfHalf end of half year
|
|
func (now *Now) EndOfHalf() time.Time {
|
|
return now.BeginningOfHalf().AddDate(0, 6, 0).Add(-time.Nanosecond)
|
|
}
|
|
|
|
// EndOfYear end of year
|
|
func (now *Now) EndOfYear() time.Time {
|
|
return now.BeginningOfYear().AddDate(1, 0, 0).Add(-time.Nanosecond)
|
|
}
|
|
|
|
// Monday monday
|
|
/*
|
|
func (now *Now) Monday() time.Time {
|
|
t := now.BeginningOfDay()
|
|
weekday := int(t.Weekday())
|
|
if weekday == 0 {
|
|
weekday = 7
|
|
}
|
|
return t.AddDate(0, 0, -weekday+1)
|
|
}
|
|
*/
|
|
|
|
func (now *Now) Monday(strs ...string) time.Time {
|
|
var parseTime time.Time
|
|
var err error
|
|
if len(strs) > 0 {
|
|
parseTime, err = now.Parse(strs...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
parseTime = now.BeginningOfDay()
|
|
}
|
|
weekday := int(parseTime.Weekday())
|
|
if weekday == 0 {
|
|
weekday = 7
|
|
}
|
|
return parseTime.AddDate(0, 0, -weekday+1)
|
|
}
|
|
|
|
func (now *Now) Sunday(strs ...string) time.Time {
|
|
var parseTime time.Time
|
|
var err error
|
|
if len(strs) > 0 {
|
|
parseTime, err = now.Parse(strs...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
parseTime = now.BeginningOfDay()
|
|
}
|
|
weekday := int(parseTime.Weekday())
|
|
if weekday == 0 {
|
|
weekday = 7
|
|
}
|
|
return parseTime.AddDate(0, 0, (7 - weekday))
|
|
}
|
|
|
|
// EndOfSunday end of sunday
|
|
func (now *Now) EndOfSunday() time.Time {
|
|
return New(now.Sunday()).EndOfDay()
|
|
}
|
|
|
|
// Quarter returns the yearly quarter
|
|
func (now *Now) Quarter() uint {
|
|
return (uint(now.Month())-1)/3 + 1
|
|
}
|
|
|
|
func (now *Now) parseWithFormat(str string, location *time.Location) (t time.Time, err error) {
|
|
for _, format := range now.TimeFormats {
|
|
t, err = time.ParseInLocation(format, str, location)
|
|
|
|
if err == nil {
|
|
return
|
|
}
|
|
}
|
|
err = errors.New("Can't parse string as time: " + str)
|
|
return
|
|
}
|
|
|
|
var hasTimeRegexp = regexp.MustCompile(`(\s+|^\s*|T)\d{1,2}((:\d{1,2})*|((:\d{1,2}){2}\.(\d{3}|\d{6}|\d{9})))(\s*$|[Z+-])`) // match 15:04:05, 15:04:05.000, 15:04:05.000000 15, 2017-01-01 15:04, 2021-07-20T00:59:10Z, 2021-07-20T00:59:10+08:00, 2021-07-20T00:00:10-07:00 etc
|
|
var onlyTimeRegexp = regexp.MustCompile(`^\s*\d{1,2}((:\d{1,2})*|((:\d{1,2}){2}\.(\d{3}|\d{6}|\d{9})))\s*$`) // match 15:04:05, 15, 15:04:05.000, 15:04:05.000000, etc
|
|
|
|
// Parse parse string to time
|
|
func (now *Now) Parse(strs ...string) (t time.Time, err error) {
|
|
var (
|
|
setCurrentTime bool
|
|
parseTime []int
|
|
currentLocation = now.Location()
|
|
onlyTimeInStr = true
|
|
currentTime = formatTimeToList(now.Time)
|
|
)
|
|
|
|
for _, str := range strs {
|
|
hasTimeInStr := hasTimeRegexp.MatchString(str) // match 15:04:05, 15
|
|
onlyTimeInStr = hasTimeInStr && onlyTimeInStr && onlyTimeRegexp.MatchString(str)
|
|
if t, err = now.parseWithFormat(str, currentLocation); err == nil {
|
|
location := t.Location()
|
|
parseTime = formatTimeToList(t)
|
|
|
|
for i, v := range parseTime {
|
|
// Don't reset hour, minute, second if current time str including time
|
|
if hasTimeInStr && i <= 3 {
|
|
continue
|
|
}
|
|
|
|
// If value is zero, replace it with current time
|
|
if v == 0 {
|
|
if setCurrentTime {
|
|
parseTime[i] = currentTime[i]
|
|
}
|
|
} else {
|
|
setCurrentTime = true
|
|
}
|
|
|
|
// if current time only includes time, should change day, month to current time
|
|
if onlyTimeInStr {
|
|
if i == 4 || i == 5 {
|
|
parseTime[i] = currentTime[i]
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
t = time.Date(parseTime[6], time.Month(parseTime[5]), parseTime[4], parseTime[3], parseTime[2], parseTime[1], parseTime[0], location)
|
|
currentTime = formatTimeToList(t)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// MustParse must parse string to time or it will panic
|
|
func (now *Now) MustParse(strs ...string) (t time.Time) {
|
|
t, err := now.Parse(strs...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return t
|
|
}
|
|
|
|
// Between check time between the begin, end time or not
|
|
func (now *Now) Between(begin, end string) bool {
|
|
beginTime := now.MustParse(begin)
|
|
endTime := now.MustParse(end)
|
|
return now.After(beginTime) && now.Before(endTime)
|
|
}
|