Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion rules/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package rules
import "time"

type Context struct {
Text string
Source string
Copy link
Owner

@olebedev olebedev Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this here? I thought that it's better to capture surrounding text if needed by the rule, isn't it?

/cc @LeonB

Text string

// accumulator of relative values
Duration time.Duration
Expand Down
1 change: 1 addition & 0 deletions rules/en/en.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var All = []rules.Rule{
CasualTime(rules.Override),
Hour(rules.Override),
HourMinute(rules.Override),
HourMinuteSecond(rules.Override),
Deadline(rules.Override),
PastTime(rules.Override),
ExactMonthDate(rules.Override),
Expand Down
18 changes: 18 additions & 0 deletions rules/en/hour.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ func Hour(s rules.Strategy) rules.Rule {
return false, nil
}

// Check if previous character starts with a time separator. If so:
// skip this rule
if m.Left > 0 {
prevChar := c.Source[m.Left-1 : m.Left]
if prevChar == ":" || prevChar == ":" || prevChar == "-" {
return false, nil
}
}

// Check if next character starts with a time separator. If so:
// skip this rule
if m.Right+1 < len(c.Source) {
nextChar := c.Source[m.Right : m.Right+1]
if nextChar == ":" || nextChar == ":" || nextChar == "-" {
return false, nil
}
}

hour, err := strconv.Atoi(m.Captures[0])
if err != nil {
return false, errors.Wrap(err, "hour rule")
Expand Down
18 changes: 18 additions & 0 deletions rules/en/hour_minute.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ func HourMinute(s rules.Strategy) rules.Rule {
return false, nil
}

// Check if previous character starts with a time separator. If so:
// skip this rule
if m.Left > 0 {
prevChar := c.Source[m.Left-1 : m.Left]
if prevChar == ":" || prevChar == ":" || prevChar == "-" {
return false, nil
}
}

// Check if next character starts with a time separator. If so:
// skip this rule
if m.Right+1 < len(c.Source) {
nextChar := c.Source[m.Right : m.Right+1]
if nextChar == ":" || nextChar == ":" || nextChar == "-" {
return false, nil
}
}

hour, err := strconv.Atoi(m.Captures[0])
if err != nil {
return false, errors.Wrap(err, "hour minute rule")
Expand Down
81 changes: 81 additions & 0 deletions rules/en/hour_minute_second.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package en

import (
"regexp"
"strconv"
"time"

"github.com/olebedev/when/rules"
"github.com/pkg/errors"
)

/*
{"05:30:10", 0, "05:30:10", 0},
{"05-30-10", 0, "05-30-10", 0},
{"05.30.10", 0, "05.30.10", 0},
*/

func HourMinuteSecond(s rules.Strategy) rules.Rule {
return &rules.F{
RegExp: regexp.MustCompile("(?i)(?:\\W|^)" +
"((?:[0-1]{0,1}[0-9])|(?:2[0-3]))" +
"(?:\\:|:|\\-)" +
"((?:[0-5][0-9]))" +
"(?:\\:|:|\\-)" +
"((?:[0-5][0-9]))" +
"(?:\\s*(A\\.|P\\.|A\\.M\\.|P\\.M\\.|AM?|PM?))?" +
"(?:\\W|$)"),
Applier: func(m *rules.Match, c *rules.Context, o *rules.Options, ref time.Time) (bool, error) {
if (c.Hour != nil || c.Minute != nil || c.Second != nil) && s != rules.Override {
return false, nil
}

hour, err := strconv.Atoi(m.Captures[0])
if err != nil {
return false, errors.Wrap(err, "hour minute second rule")
}

minutes, err := strconv.Atoi(m.Captures[1])
if err != nil {
return false, errors.Wrap(err, "hour minute second rule")
}

if minutes > 59 {
return false, nil
}
c.Minute = &minutes

seconds, err := strconv.Atoi(m.Captures[2])
if err != nil {
return false, errors.Wrap(err, "hour minute second rule")
}

if seconds > 59 {
return false, nil
}
c.Second = &seconds

if m.Captures[3] != "" {
if hour > 12 {
return false, nil
}
switch m.Captures[3][0] {
case 65, 97: // am
c.Hour = &hour
case 80, 112: // pm
if hour < 12 {
hour += 12
}
c.Hour = &hour
}
} else {
if hour > 23 {
return false, nil
}
c.Hour = &hour
}

return true, nil
},
}
}
43 changes: 43 additions & 0 deletions rules/en/hour_minute_second_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package en_test

import (
"testing"
"time"

"github.com/olebedev/when"
"github.com/olebedev/when/rules"
"github.com/olebedev/when/rules/en"
)

func TestHourMinuteSecond(t *testing.T) {
w := when.New(nil)
w.Add(en.HourMinuteSecond(rules.Override))

fixtok := []Fixture{
{"5:30:10pm", 0, "5:30:10pm", (17 * time.Hour) + (30 * time.Minute) + (10 * time.Second)},
}

fixtnil := []Fixture{
{"28:30:30pm", 0, "", 0},
{"12:61:30pm", 0, "", 0},
{"24:10:61", 0, "", 0},
{"24:10:61", 0, "", 0},
}

ApplyFixtures(t, "en.HourMinuteSecond", w, fixtok)
ApplyFixturesNil(t, "on.HourMinuteSecond nil", w, fixtnil)

w.Add(en.Hour(rules.Skip))
ApplyFixtures(t, "en.HourMinuteSecond|en.Hour", w, fixtok)
ApplyFixturesNil(t, "on.HourMinuteSecond|en.Hour nil", w, fixtnil)

w = when.New(nil)
w.Add(
en.HourMinuteSecond(rules.Override),
en.Hour(rules.Override),
en.HourMinute(rules.Override),
)

ApplyFixtures(t, "en.Hour|en.HourMinute|en.HourMinuteSecond", w, fixtok)
ApplyFixturesNil(t, "on.Hour|en.HourMinute|en.HourMinuteSecond nil", w, fixtnil)
}
2 changes: 1 addition & 1 deletion when.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (p *Parser) Parse(text string, base time.Time) (*Result, error) {
sort.Sort(rules.MatchByOrder(matches))
}

ctx := &rules.Context{Text: res.Text}
ctx := &rules.Context{Text: res.Text, Source: res.Source}
applied := false
for _, applier := range matches {
ok, err := applier.Apply(ctx, p.options, res.Time)
Expand Down