io-da/schedule

View on GitHub
between_expression.go

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
package schedule

import "time"

// BetweenExpression is the struct used to create cron between expressions.
type BetweenExpression struct {
    x    int
    y    int
    step int
}

// Between is an expression that generates integers between the provided parameters (*inclusive*).
func Between(x int, y int) *BetweenExpression {
    if x > y {
        panic("schedule: invalid BetweenExpression expression")
    }

    return &BetweenExpression{
        x:    x,
        y:    y,
        step: 1,
    }
}

// BetweenMilliseconds uses the regular between logic, ensuring valid millisecond parameters.
func BetweenMilliseconds(x int, y int) *BetweenExpression {
    validateMillisecond(x)
    validateMillisecond(y)
    return Between(x, y)
}

// BetweenSeconds uses the regular between logic, ensuring valid second parameters.
func BetweenSeconds(x int, y int) *BetweenExpression {
    validateSecond(x)
    validateSecond(y)
    return Between(x, y)
}

// BetweenMinutes uses the regular between logic, ensuring valid minute parameters.
func BetweenMinutes(x int, y int) *BetweenExpression {
    validateMinute(x)
    validateMinute(y)
    return Between(x, y)
}

// BetweenHours uses the regular between logic, ensuring valid hour parameters.
func BetweenHours(x int, y int) *BetweenExpression {
    validateHour(x)
    validateHour(y)
    return Between(x, y)
}

// BetweenDays uses the regular between logic, ensuring valid day parameters.
func BetweenDays(x int, y int) *BetweenExpression {
    validateDay(x)
    validateDay(y)
    return Between(x, y)
}

// BetweenWeekdays uses the regular between logic, ensuring valid time.Weekday parameters.
func BetweenWeekdays(x time.Weekday, y time.Weekday) *BetweenExpression {
    xI := int(x)
    yI := int(y)
    validateWeekday(xI)
    validateWeekday(yI)
    return Between(xI, yI)
}

// BetweenMonths uses the regular between logic, ensuring valid time.Month parameters.
func BetweenMonths(x time.Month, y time.Month) *BetweenExpression {
    xI := int(x)
    yI := int(y)
    validateMonth(xI)
    validateMonth(yI)
    return Between(xI, yI)
}

// BetweenYears uses the regular between logic, ensuring valid year parameters.
func BetweenYears(x int, y int) *BetweenExpression {
    validateYear(x)
    validateYear(y)
    return Between(x, y)
}

// Every allows optional specification of the stepping used for the between logic.
// It's important to understand the behavior of the expression when step > 1. It may produce some unexpected values.
// Example: Between(0,10).Every(3)
//        - Next(-1, true || false)  = 0
//        - Next(0, true)   = 0
//        - Next(0, false)  = 3
//        - Next(1, true || false)  = 3
//        - Next(3, false)  = 6
//        - Next(6, false)  = 9
//        - Next(9, false)  = 10
//        - Next(10, true || false) = 10
func (exp *BetweenExpression) Every(s int) *BetweenExpression {
    if s < 1 {
        panic("schedule: invalid step value")
    }
    exp.step = s
    return exp
}

// Next allows retrieval of the next value from this expression.
// Expressions are stateless, the determination of their next value is based on input.
// Given a valid expression value, the parameter inc is used to specify if it should be included in the output.
// Given the last value of the expression or above, the inc parameter is ignored.
// It returns the next value according to provided parameters and a boolean indicating if it is the last value.
func (exp *BetweenExpression) Next(from int, inc bool) (int, bool) {
    if from < exp.x || inc && from == exp.x {
        return exp.x, false
    }

    if from >= exp.y {
        return exp.y, true
    }

    diff := exp.step - (from-exp.x)%exp.step
    if inc && diff == exp.step {
        diff = 0
    }

    next := from + diff
    if next >= exp.y {
        return exp.y, true
    }
    return next, false
}

// Contains verifies if the provided value belongs to this expression.
func (exp *BetweenExpression) Contains(val int) bool {
    if val < exp.x || val > exp.y {
        return false
    }

    if val == exp.x || val == exp.y {
        return true
    }

    return (exp.step - (val-exp.x)%exp.step) == exp.step
}