Exemple #1
0
// parseDate converts the given datestring (from one of the allowable formats) into a millisecond offset from the Unix epoch.
func parseDate(date string, now time.Time) (int64, error) {

	if date == "now" {
		return now.Unix() * 1000, nil
	}

	// Millisecond epoch timestamp.
	if epoch, err := strconv.ParseInt(date, 10, 0); err == nil {
		return epoch, nil
	}

	relativeTime, err := function.StringToDuration(date)
	if err == nil {
		// A relative date.
		if relativeTime > 0 {
			return -1, fmt.Errorf("relative times should be negative: %s", date)
		}
		return now.Add(relativeTime).Unix() * 1000, nil
	}

	errorMessage := fmt.Sprintf("Expected formatted date or relative time but got '%s'", date)
	for _, format := range dateFormats {
		t, err := time.Parse(format, date)
		if err == nil {
			return t.Unix()*1000 + int64(t.Nanosecond()/1000000), nil
		}
	}
	return -1, errors.New(errorMessage)
}
Exemple #2
0
func (p *Parser) addDurationNode(value string) {
	duration, err := function.StringToDuration(value)
	p.pushNode(&durationExpression{value, duration})
	if err != nil {
		p.flagSyntaxError(SyntaxError{
			token:   value,
			message: fmt.Sprintf("'%s' is not a valid duration: %s", value, err.Error()),
		})
	}
}
Exemple #3
0
func (p *Parser) insertPropertyKeyValue() {
	valueNode, ok := p.popNode(evaluationContextValuePointer).(*evaluationContextValue)
	if !ok {
		p.flagTypeAssertion()
		return
	}
	keyNode, ok := p.popNode(evaluationContextKeyPointer).(*evaluationContextKey)
	if !ok {
		p.flagTypeAssertion()
		return
	}
	contextNode, ok := p.popNode(evaluationContextNodePointer).(*evaluationContextNode)
	if !ok {
		p.flagTypeAssertion()
		return
	}

	key := keyNode.key
	value := valueNode.value
	// Authenticate the validity of the given key and value...
	// The key must be one of "sample"(by), "from", "to", "resolution"

	// First check that the key has been assigned only once:
	if contextNode.assigned[key] {
		p.flagSyntaxError(SyntaxError{
			token:   key,
			message: fmt.Sprintf("Key %s has already been assigned", key),
		})
	}
	contextNode.assigned[key] = true

	switch key {
	case "sample":
		// If the key is "sample", it means we're in a "sample by" declaration.
		// Only three possible sample methods are defined: min, max, or mean.
		switch value {
		case "max":
			contextNode.SampleMethod = api.SampleMax
		case "min":
			contextNode.SampleMethod = api.SampleMin
		case "mean":
			contextNode.SampleMethod = api.SampleMean
		default:
			p.flagSyntaxError(SyntaxError{
				token:   value,
				message: fmt.Sprintf("Expected sampling method 'max', 'min', or 'mean' but got %s", value),
			})
		}
	case "from", "to":
		var unix int64
		var err error
		now := time.Now()
		if unix, err = parseDate(value, now); err != nil {
			p.flagSyntaxError(SyntaxError{
				token:   value,
				message: err.Error(),
			})
		}
		if key == "from" {
			contextNode.Start = unix
		} else {
			contextNode.End = unix
		}
	case "resolution":
		// The value must be determined to be an int if the key is "resolution".
		if intValue, err := strconv.ParseInt(value, 10, 64); err == nil {
			contextNode.Resolution = intValue
		} else if duration, err := function.StringToDuration(value); err == nil {
			contextNode.Resolution = int64(duration / time.Millisecond)
		} else {
			p.flagSyntaxError(SyntaxError{
				token:   value,
				message: fmt.Sprintf("Expected number but parse failed; %s", err.Error()),
			})
		}
	default:
		p.flagSyntaxError(SyntaxError{
			token:   key,
			message: fmt.Sprintf("Unknown property key %s", key),
		})
	}
	p.pushNode(contextNode)
}