mirror of
https://github.com/MontFerret/ferret.git
synced 2025-01-16 03:21:03 +02:00
Feature/#8 datetime (#153)
This commit is contained in:
parent
d8ae6cca8b
commit
612705ca3a
@ -7,7 +7,7 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
)
|
||||
|
||||
const defaultTimeLayout = time.RFC3339
|
||||
const DefaultTimeLayout = time.RFC3339
|
||||
|
||||
type DateTime struct {
|
||||
time.Time
|
||||
@ -26,7 +26,7 @@ func NewDateTime(time time.Time) DateTime {
|
||||
}
|
||||
|
||||
func ParseDateTime(input interface{}) (DateTime, error) {
|
||||
return ParseDateTimeWith(input, defaultTimeLayout)
|
||||
return ParseDateTimeWith(input, DefaultTimeLayout)
|
||||
}
|
||||
|
||||
func ParseDateTimeWith(input interface{}, layout string) (DateTime, error) {
|
||||
|
33
pkg/stdlib/datetime/date.go
Normal file
33
pkg/stdlib/datetime/date.go
Normal file
@ -0,0 +1,33 @@
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
// Date convert RFC3339 date time string to DateTime object.
|
||||
// @params timeString (String) - string in RFC3339 format.
|
||||
// @return (DateTime) - new DateTime object derived from timeString.
|
||||
func Date(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.StringType)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
timeStrings := args[0].(values.String)
|
||||
|
||||
t, err := time.Parse(values.DefaultTimeLayout, timeStrings.String())
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewDateTime(t), nil
|
||||
}
|
49
pkg/stdlib/datetime/date_test.go
Normal file
49
pkg/stdlib/datetime/date_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package datetime_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
|
||||
)
|
||||
|
||||
func TestDate(t *testing.T) {
|
||||
tcs := []*testCase{
|
||||
&testCase{
|
||||
Name: "When more than 1 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{
|
||||
values.NewString("string"),
|
||||
values.NewInt(0),
|
||||
},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When 0 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When incorrect timeStrings",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{
|
||||
values.NewString("bla-bla"),
|
||||
},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When correct timeString in RFC3339 format",
|
||||
Expected: mustDefaultLayoutDt("1999-02-07T15:04:05Z"),
|
||||
Args: []core.Value{
|
||||
values.NewString("1999-02-07T15:04:05Z"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
tc.Do(t, datetime.Date)
|
||||
}
|
||||
}
|
28
pkg/stdlib/datetime/dayofweek.go
Normal file
28
pkg/stdlib/datetime/dayofweek.go
Normal file
@ -0,0 +1,28 @@
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
)
|
||||
|
||||
// DateDayOfWeek returns number of the weekday from the date. Sunday is the 0th day of week.
|
||||
// @params date (DateTime) - source DateTime.
|
||||
// @return (Int) - return number of the weekday.
|
||||
func DateDayOfWeek(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.DateTimeType)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
wday := args[0].(values.DateTime).Weekday()
|
||||
|
||||
return values.NewInt(int(wday)), nil
|
||||
}
|
43
pkg/stdlib/datetime/dayofweek_test.go
Normal file
43
pkg/stdlib/datetime/dayofweek_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
package datetime_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
|
||||
)
|
||||
|
||||
func TestDateDayOfWeek(t *testing.T) {
|
||||
tcs := []*testCase{
|
||||
&testCase{
|
||||
Name: "When more than 1 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{
|
||||
values.NewString("string"),
|
||||
values.NewInt(0),
|
||||
},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When 0 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When Sunday (0th day)",
|
||||
Expected: values.NewInt(0),
|
||||
Args: []core.Value{mustDefaultLayoutDt("1999-02-07T15:04:05Z")},
|
||||
},
|
||||
&testCase{
|
||||
Name: "When Monday (1th day)",
|
||||
Expected: values.NewInt(1),
|
||||
Args: []core.Value{mustDefaultLayoutDt("1999-02-08T15:04:05Z")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
tc.Do(t, datetime.DateDayOfWeek)
|
||||
}
|
||||
}
|
65
pkg/stdlib/datetime/helpers_test.go
Normal file
65
pkg/stdlib/datetime/helpers_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
package datetime_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
Name string
|
||||
Expected core.Value
|
||||
TimeArg time.Time
|
||||
Args []core.Value
|
||||
ShouldErr bool
|
||||
}
|
||||
|
||||
func (tc *testCase) Do(t *testing.T, fn core.Function) {
|
||||
Convey(tc.Name, t, func() {
|
||||
expected := tc.Expected
|
||||
|
||||
actual, err := fn(context.Background(), tc.Args...)
|
||||
|
||||
if tc.ShouldErr {
|
||||
So(err, ShouldBeError)
|
||||
expected = values.None
|
||||
} else {
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
|
||||
So(actual.Compare(expected), ShouldEqual, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func mustDefaultLayoutDt(timeString string) values.DateTime {
|
||||
dt, err := defaultLayoutDt(timeString)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return dt
|
||||
}
|
||||
|
||||
func mustLayoutDt(layout, value string) values.DateTime {
|
||||
dt, err := layoutDt(layout, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return dt
|
||||
}
|
||||
|
||||
func defaultLayoutDt(timeString string) (values.DateTime, error) {
|
||||
return layoutDt(values.DefaultTimeLayout, timeString)
|
||||
}
|
||||
|
||||
func layoutDt(layout, value string) (values.DateTime, error) {
|
||||
t, err := time.Parse(layout, value)
|
||||
if err != nil {
|
||||
return values.DateTime{}, err
|
||||
}
|
||||
return values.NewDateTime(t), nil
|
||||
}
|
@ -4,6 +4,9 @@ import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
"NOW": Now,
|
||||
"NOW": Now,
|
||||
"DATE": Date,
|
||||
"DATE_DAYOFWEEK": DateDayOfWeek,
|
||||
"DATE_YEAR": DateYear,
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,14 @@
|
||||
package datetime_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
Name string
|
||||
Expected core.Value
|
||||
TimeArg time.Time
|
||||
Args []core.Value
|
||||
ShouldErr bool
|
||||
}
|
||||
|
||||
func TestNow(t *testing.T) {
|
||||
tcs := []*testCase{
|
||||
&testCase{
|
||||
@ -33,25 +22,6 @@ func TestNow(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
tc.Do(t)
|
||||
tc.Do(t, datetime.Now)
|
||||
}
|
||||
}
|
||||
|
||||
func (tc *testCase) Do(t *testing.T) {
|
||||
Convey(tc.Name, t, func() {
|
||||
var expected core.Value
|
||||
|
||||
expected = values.NewDateTime(tc.TimeArg)
|
||||
|
||||
dt, err := datetime.Now(context.Background(), tc.Args...)
|
||||
|
||||
if tc.ShouldErr {
|
||||
So(err, ShouldBeError)
|
||||
expected = values.None
|
||||
} else {
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
|
||||
So(dt, ShouldEqual, expected)
|
||||
})
|
||||
}
|
||||
|
27
pkg/stdlib/datetime/year.go
Normal file
27
pkg/stdlib/datetime/year.go
Normal file
@ -0,0 +1,27 @@
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
// DateYear returns the year extracted from the given date.
|
||||
// @params date (DateTime) - source DateTime.
|
||||
// @return (Int) - a year number.
|
||||
func DateYear(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.DateTimeType)
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
year := args[0].(values.DateTime).Year()
|
||||
|
||||
return values.NewInt(year), nil
|
||||
}
|
43
pkg/stdlib/datetime/year_test.go
Normal file
43
pkg/stdlib/datetime/year_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
package datetime_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/datetime"
|
||||
)
|
||||
|
||||
func TestDateYear(t *testing.T) {
|
||||
tcs := []*testCase{
|
||||
&testCase{
|
||||
Name: "When more than 1 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{
|
||||
values.NewString("string"),
|
||||
values.NewInt(0),
|
||||
},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When 0 arguments",
|
||||
Expected: values.None,
|
||||
Args: []core.Value{},
|
||||
ShouldErr: true,
|
||||
},
|
||||
&testCase{
|
||||
Name: "When 1999th year",
|
||||
Expected: values.NewInt(1999),
|
||||
Args: []core.Value{mustDefaultLayoutDt("1999-02-07T15:04:05Z")},
|
||||
},
|
||||
&testCase{
|
||||
Name: "When 1629th year",
|
||||
Expected: values.NewInt(1629),
|
||||
Args: []core.Value{mustDefaultLayoutDt("1629-02-08T15:04:05Z")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
tc.Do(t, datetime.DateYear)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user