Files
olebedev-when/rules/br/deadline.go
T

116 lines
3.2 KiB
Go

package br
import (
"regexp"
"strconv"
"strings"
"time"
"github.com/AlekSi/pointer"
"github.com/olebedev/when/rules"
"github.com/pkg/errors"
)
// DeadlineOptions configures the Deadline rule.
type DeadlineOptions struct {
// Aggressive makes the "dentro de"/"em" prefix optional, so "3 dias" matches too.
Aggressive bool
}
func Deadline(s rules.Strategy, opts ...DeadlineOptions) rules.Rule {
overwrite := s == rules.Override
prefix := "(dentro\\sde|em)"
if len(opts) > 0 && opts[0].Aggressive {
prefix += "?"
}
return &rules.F{
RegExp: regexp.MustCompile(
"(?i)(?:\\W|^)" + prefix + "\\s*" +
"(?:(" + INTEGER_WORDS_PATTERN + "|[0-9]+|(?:\\s*pouc[oa](?:s|)?|algu(?:mas|m|ns)?|mei[oa]?))\\s*" +
"(segundos?|min(?:uto)?s?|horas?|dias?|semanas?|mês|meses|anos?)\\s*)" +
"(?:\\W|$)"),
Applier: func(m *rules.Match, c *rules.Context, o *rules.Options, ref time.Time) (bool, error) {
numStr := strings.TrimSpace(m.Captures[1])
var num int
var err error
if n, ok := INTEGER_WORDS[numStr]; ok {
num = n
} else if strings.Contains(numStr, "pouc") || strings.Contains(numStr, "algu") {
num = 3
} else if strings.Contains(numStr, "mei") {
// pass
} else {
num, err = strconv.Atoi(numStr)
if err != nil {
return false, errors.Wrapf(err, "convert '%s' to int", numStr)
}
}
exponent := strings.TrimSpace(m.Captures[2])
if !strings.Contains(numStr, "mei") {
switch {
case strings.Contains(exponent, "segundo"):
if c.Duration == 0 || overwrite {
c.Duration = time.Duration(num) * time.Second
}
case strings.Contains(exponent, "min"):
if c.Duration == 0 || overwrite {
c.Duration = time.Duration(num) * time.Minute
}
case strings.Contains(exponent, "hora"):
if c.Duration == 0 || overwrite {
c.Duration = time.Duration(num) * time.Hour
}
case strings.Contains(exponent, "dia"):
if c.Duration == 0 || overwrite {
c.Duration = time.Duration(num) * 24 * time.Hour
}
case strings.Contains(exponent, "semana"):
if c.Duration == 0 || overwrite {
c.Duration = time.Duration(num) * 7 * 24 * time.Hour
}
case strings.Contains(exponent, "mês"), strings.Contains(exponent, "meses"):
if c.Month == nil || overwrite {
c.Month = pointer.ToInt((int(ref.Month()) + num) % 12)
}
case strings.Contains(exponent, "ano"):
if c.Year == nil || overwrite {
c.Year = pointer.ToInt(ref.Year() + num)
}
}
} else {
switch {
case strings.Contains(exponent, "hora"):
if c.Duration == 0 || overwrite {
c.Duration = 30 * time.Minute
}
case strings.Contains(exponent, "dia"):
if c.Duration == 0 || overwrite {
c.Duration = 12 * time.Hour
}
case strings.Contains(exponent, "semana"):
if c.Duration == 0 || overwrite {
c.Duration = 7 * 12 * time.Hour
}
case strings.Contains(exponent, "mês"), strings.Contains(exponent, "meses"):
if c.Duration == 0 || overwrite {
// 2 weeks
c.Duration = 14 * 24 * time.Hour
}
case strings.Contains(exponent, "ano"):
if c.Month == nil || overwrite {
c.Month = pointer.ToInt((int(ref.Month()) + 6) % 12)
}
}
}
return true, nil
},
}
}