Skip to content

Commit 5f57958

Browse files
author
=
committed
added DateCompare function
1 parent b4a8c8b commit 5f57958

File tree

5 files changed

+298
-49
lines changed

5 files changed

+298
-49
lines changed

pkg/stdlib/datetime/add_subtract.go

+8-29
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ package datetime
22

33
import (
44
"context"
5-
"strings"
6-
"time"
75

86
"github.com/MontFerret/ferret/pkg/runtime/core"
97
"github.com/MontFerret/ferret/pkg/runtime/values"
10-
"github.com/pkg/errors"
118
)
129

1310
var (
@@ -40,12 +37,14 @@ func DateAdd(_ context.Context, args ...core.Value) (core.Value, error) {
4037
return values.None, err
4138
}
4239

43-
dt, err := addUnit(date, int(amount), unit.String())
40+
u, err := UnitFromString(unit.String())
4441
if err != nil {
4542
return values.None, err
4643
}
4744

48-
return dt, nil
45+
tm := AddUnit(date.Time, int(amount), u)
46+
47+
return values.NewDateTime(tm), nil
4948
}
5049

5150
// DateSubtract subtract amount given in unit to date.
@@ -68,12 +67,14 @@ func DateSubtract(_ context.Context, args ...core.Value) (core.Value, error) {
6867
return values.None, err
6968
}
7069

71-
dt, err := addUnit(date, -1*int(amount), unit.String())
70+
u, err := UnitFromString(unit.String())
7271
if err != nil {
7372
return values.None, err
7473
}
7574

76-
return dt, nil
75+
tm := AddUnit(date.Time, -1*int(amount), u)
76+
77+
return values.NewDateTime(tm), nil
7778
}
7879

7980
func getArgs(args []core.Value) (values.DateTime, values.Int, values.String, error) {
@@ -97,25 +98,3 @@ func getArgs(args []core.Value) (values.DateTime, values.Int, values.String, err
9798

9899
return date, amount, unit, nil
99100
}
100-
101-
func addUnit(dt values.DateTime, amount int, unit string) (values.DateTime, error) {
102-
switch strings.ToLower(unit) {
103-
case "y", "year", "years":
104-
return values.NewDateTime(dt.AddDate(amount*1, 0, 0)), nil
105-
case "m", "month", "months":
106-
return values.NewDateTime(dt.AddDate(0, amount*1, 0)), nil
107-
case "w", "week", "weeks":
108-
return values.NewDateTime(dt.AddDate(0, 0, amount*7)), nil
109-
case "d", "day", "days":
110-
return values.NewDateTime(dt.AddDate(0, 0, amount*1)), nil
111-
case "h", "hour", "hours":
112-
return values.NewDateTime(dt.Add(time.Hour)), nil
113-
case "i", "minute", "minutes":
114-
return values.NewDateTime(dt.Add(time.Minute)), nil
115-
case "s", "second", "seconds":
116-
return values.NewDateTime(dt.Add(time.Second)), nil
117-
case "f", "millisecond", "milliseconds":
118-
return values.NewDateTime(dt.Add(time.Millisecond)), nil
119-
}
120-
return values.DateTime{}, errors.Errorf("no such unit '%s'", unit)
121-
}

pkg/stdlib/datetime/compare.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package datetime
2+
3+
import (
4+
"github.com/pkg/errors"
5+
6+
"context"
7+
8+
"github.com/MontFerret/ferret/pkg/runtime/core"
9+
"github.com/MontFerret/ferret/pkg/runtime/values"
10+
)
11+
12+
// DateCompare check if two partial dates match.
13+
// @params date1, date2 (DateTime) - comparable dates.
14+
// @params unitRangeStart (String) - unit to start from.
15+
// @params unitRangeEnd (String, Optional) - unit to end with.
16+
// Error will be returned if unitRangeStart unit less that unitRangeEnd.
17+
// @return (Boolean) - true if the dates match, else false.
18+
func DateCompare(_ context.Context, args ...core.Value) (core.Value, error) {
19+
err := core.ValidateArgs(args, 3, 4)
20+
if err != nil {
21+
return values.None, err
22+
}
23+
24+
err = core.ValidateValueTypePairs(
25+
core.PairValueType{Value: args[0], Types: sliceDateTime},
26+
core.PairValueType{Value: args[1], Types: sliceDateTime},
27+
core.PairValueType{Value: args[2], Types: sliceStringType},
28+
)
29+
if err != nil {
30+
return values.None, err
31+
}
32+
33+
date1 := args[0].(values.DateTime)
34+
date2 := args[1].(values.DateTime)
35+
rangeStart := args[2].(values.String)
36+
rangeEnd := values.NewString("millisecond")
37+
38+
if len(args) == 4 {
39+
if err = core.ValidateType(args[3], core.StringType); err != nil {
40+
return values.None, err
41+
}
42+
rangeEnd = args[3].(values.String)
43+
}
44+
45+
unitStart, err := UnitFromString(rangeStart.String())
46+
if err != nil {
47+
return values.None, err
48+
}
49+
50+
unitEnd, err := UnitFromString(rangeEnd.String())
51+
if err != nil {
52+
return values.None, err
53+
}
54+
55+
if unitStart < unitEnd {
56+
return values.None, errors.Errorf("start unit less that end unit")
57+
}
58+
59+
for u := unitEnd; u <= unitStart; u++ {
60+
if IsDatesEqual(date1.Time, date2.Time, u) {
61+
return values.NewBoolean(true), nil
62+
}
63+
}
64+
65+
return values.NewBoolean(false), nil
66+
}

pkg/stdlib/datetime/compare_test.go

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package datetime_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/MontFerret/ferret/pkg/runtime/core"
7+
"github.com/MontFerret/ferret/pkg/runtime/values"
8+
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
9+
)
10+
11+
func TestDateCompare(t *testing.T) {
12+
expectedTrue := values.NewBoolean(true)
13+
expectedFalse := values.NewBoolean(false)
14+
15+
tcs := []*testCase{
16+
&testCase{
17+
Name: "When less than 3 arguments",
18+
Expected: values.None,
19+
Args: []core.Value{values.NewInt(0), values.NewInt(0)},
20+
ShouldErr: true,
21+
},
22+
&testCase{
23+
Name: "When more than 4 arguments",
24+
Expected: values.None,
25+
Args: []core.Value{
26+
values.NewInt(0), values.NewInt(0), values.NewInt(0),
27+
values.NewInt(0), values.NewInt(0),
28+
},
29+
ShouldErr: true,
30+
},
31+
&testCase{
32+
Name: "when wrong type of arguments",
33+
Expected: values.None,
34+
Args: []core.Value{
35+
values.NewCurrentDateTime(),
36+
values.NewCurrentDateTime(),
37+
values.NewInt(0),
38+
},
39+
ShouldErr: true,
40+
},
41+
&testCase{
42+
Name: "when wrong type of optional argument",
43+
Expected: values.None,
44+
Args: []core.Value{
45+
values.NewCurrentDateTime(),
46+
values.NewCurrentDateTime(),
47+
values.NewString("year"),
48+
values.NewInt(0),
49+
},
50+
ShouldErr: true,
51+
},
52+
&testCase{
53+
Name: "when start unit less that end unit",
54+
Expected: values.None,
55+
Args: []core.Value{
56+
values.NewCurrentDateTime(),
57+
values.NewCurrentDateTime(),
58+
values.NewString("day"),
59+
values.NewString("year"),
60+
},
61+
ShouldErr: true,
62+
},
63+
&testCase{
64+
Name: "when years are equal",
65+
Expected: expectedTrue,
66+
Args: []core.Value{
67+
values.NewCurrentDateTime(),
68+
values.NewCurrentDateTime(),
69+
values.NewString("year"),
70+
},
71+
},
72+
&testCase{
73+
Name: "when years are not equal",
74+
Expected: expectedFalse,
75+
Args: []core.Value{
76+
mustLayoutDt("2006-01-02", "1999-02-07"),
77+
mustLayoutDt("2006-01-02", "2000-02-07"),
78+
values.NewString("year"),
79+
values.NewString("year"),
80+
},
81+
},
82+
&testCase{
83+
Name: "when months are equal",
84+
Expected: expectedTrue,
85+
Args: []core.Value{
86+
mustLayoutDt("2006-01-02", "1999-02-07"),
87+
mustLayoutDt("2006-01-02", "2000-02-09"),
88+
values.NewString("year"),
89+
values.NewString("days"),
90+
},
91+
},
92+
&testCase{
93+
Name: "when days are equal",
94+
Expected: expectedTrue,
95+
Args: []core.Value{
96+
values.NewCurrentDateTime(),
97+
values.NewCurrentDateTime(),
98+
values.NewString("days"),
99+
values.NewString("days"),
100+
},
101+
},
102+
}
103+
104+
for _, tc := range tcs {
105+
tc.Do(t, datetime.DateCompare)
106+
}
107+
}

pkg/stdlib/datetime/diff.go

+4-20
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package datetime
22

33
import (
44
"context"
5-
"strings"
65

76
"github.com/MontFerret/ferret/pkg/runtime/core"
87
"github.com/MontFerret/ferret/pkg/runtime/values"
9-
"github.com/pkg/errors"
108
)
119

1210
// DateDiff returns the difference between two dates in given time unit.
@@ -71,23 +69,9 @@ func DateDiff(_ context.Context, args ...core.Value) (core.Value, error) {
7169
}
7270

7371
func nsecToUnit(nsec float64, unit string) (float64, error) {
74-
switch strings.ToLower(unit) {
75-
case "y", "year", "years":
76-
return nsec / 31536e12, nil
77-
case "m", "month", "months":
78-
return nsec / 26784e11, nil
79-
case "w", "week", "weeks":
80-
return nsec / 6048e11, nil
81-
case "d", "day", "days":
82-
return nsec / 864e11, nil
83-
case "h", "hour", "hours":
84-
return nsec / 36e11, nil
85-
case "i", "minute", "minutes":
86-
return nsec / 6e10, nil
87-
case "s", "second", "seconds":
88-
return nsec / 1e9, nil
89-
case "f", "millisecond", "milliseconds":
90-
return nsec / 1e6, nil
72+
u, err := UnitFromString(unit)
73+
if err != nil {
74+
return -1, err
9175
}
92-
return -1, errors.Errorf("no such unit '%s'", unit)
76+
return nsec / u.Nanosecond(), nil
9377
}

0 commit comments

Comments
 (0)