mirror of
				https://github.com/MontFerret/ferret.git
				synced 2025-10-30 23:37:40 +02:00 
			
		
		
		
	added DATE_DAYOFYEAR, DATE_MILLISECOND, DATE_LEAPYEAR, DATE_QUARTER, DATE_DAYS_IN_MONTH, DATE_FORMAT functions (#157)
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -22,7 +22,7 @@ install: | ||||
| 	dep ensure | ||||
|  | ||||
| test: | ||||
| 	go test -race ${DIR_PKG}/... | ||||
| 	go test -race -v ${DIR_PKG}/... | ||||
|  | ||||
| cover: | ||||
| 	go test -race -coverprofile=coverage.txt -covermode=atomic ${DIR_PKG}/... && \ | ||||
|   | ||||
							
								
								
									
										29
									
								
								pkg/stdlib/datetime/dayofyear.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								pkg/stdlib/datetime/dayofyear.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| ) | ||||
|  | ||||
| // DateDayOfYear returns the day of year number of date. | ||||
| // The return value range from 1 to 365 (366 in a leap year). | ||||
| // @params date (DateTime) - source DateTime. | ||||
| // @return (Int) - a day of year number. | ||||
| func DateDayOfYear(_ 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 | ||||
| 	} | ||||
|  | ||||
| 	dayOfYear := args[0].(values.DateTime).YearDay() | ||||
|  | ||||
| 	return values.NewInt(dayOfYear), nil | ||||
| } | ||||
							
								
								
									
										51
									
								
								pkg/stdlib/datetime/dayofyear_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								pkg/stdlib/datetime/dayofyear_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package datetime_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/datetime" | ||||
| ) | ||||
|  | ||||
| func TestDateDayOfYear(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 38th day of the year", | ||||
| 			Expected: values.NewInt(38), | ||||
| 			Args:     []core.Value{mustDefaultLayoutDt("1999-02-07T15:04:05Z")}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When 59th day of the year", | ||||
| 			Expected: values.NewInt(59), | ||||
| 			Args:     []core.Value{mustDefaultLayoutDt("1629-02-28T15:59:05Z")}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When 366th day of the year", | ||||
| 			Expected: values.NewInt(366), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1972, time.December, 31, 0, 0, 0, 0, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateDayOfYear) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										49
									
								
								pkg/stdlib/datetime/daysinmonth.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								pkg/stdlib/datetime/daysinmonth.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| var daysCount = map[time.Month]int{ | ||||
| 	time.January:   31, | ||||
| 	time.February:  28, | ||||
| 	time.March:     31, | ||||
| 	time.April:     30, | ||||
| 	time.May:       31, | ||||
| 	time.June:      30, | ||||
| 	time.July:      30, | ||||
| 	time.August:    31, | ||||
| 	time.September: 30, | ||||
| 	time.October:   31, | ||||
| 	time.November:  30, | ||||
| 	time.December:  31, | ||||
| } | ||||
|  | ||||
| // DateDaysInMonth returns the number of days in the month of date. | ||||
| // @params date (DateTime) - source DateTime. | ||||
| // @return (Int) - number of the days. | ||||
| func DateDaysInMonth(_ 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 | ||||
| 	} | ||||
|  | ||||
| 	dt := args[0].(values.DateTime) | ||||
| 	month := dt.Month() | ||||
| 	count := daysCount[month] | ||||
|  | ||||
| 	if month == time.February && isLeap(dt.Year()) { | ||||
| 		count++ | ||||
| 	} | ||||
|  | ||||
| 	return values.NewInt(count), nil | ||||
| } | ||||
							
								
								
									
										62
									
								
								pkg/stdlib/datetime/daysinmonth_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								pkg/stdlib/datetime/daysinmonth_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package datetime_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/datetime" | ||||
| ) | ||||
|  | ||||
| func TestDateDateDaysInMonth(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 Feb and a leap year", | ||||
| 			Expected: values.NewInt(29), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1972, time.February, 1, 1, 1, 1, 1, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When Feb and not a leap year", | ||||
| 			Expected: values.NewInt(28), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1999, time.February, 1, 1, 1, 1, 1, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When January", | ||||
| 			Expected: values.NewInt(31), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1999, time.January, 1, 1, 1, 1, 1, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When November", | ||||
| 			Expected: values.NewInt(30), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1999, time.November, 1, 1, 1, 1, 1, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateDaysInMonth) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										33
									
								
								pkg/stdlib/datetime/format.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								pkg/stdlib/datetime/format.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // DateFormat format date according to the given format string. | ||||
| // @params date (DateTime) - source DateTime object. | ||||
| // @return (String) - formatted date. | ||||
| func DateFormat(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, 2) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	date := args[0].(values.DateTime) | ||||
| 	format := args[1].(values.String).String() | ||||
|  | ||||
| 	return values.NewString(date.Format(format)), nil | ||||
| } | ||||
							
								
								
									
										115
									
								
								pkg/stdlib/datetime/format_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								pkg/stdlib/datetime/format_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| package datetime_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/datetime" | ||||
| ) | ||||
|  | ||||
| func TestDateFormat(t *testing.T) { | ||||
| 	tcs := []*testCase{ | ||||
| 		&testCase{ | ||||
| 			Name:     "When more than 2 arguments", | ||||
| 			Expected: values.None, | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewString("string"), | ||||
| 				values.NewInt(0), | ||||
| 				values.NewArray(0), | ||||
| 			}, | ||||
| 			ShouldErr: true, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When less than 2 arguments", | ||||
| 			Expected: values.None, | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewInt(0), | ||||
| 			}, | ||||
| 			ShouldErr: true, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When first argument is wrong", | ||||
| 			Expected: values.None, | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewInt(0), | ||||
| 				values.NewString(time.RFC822), | ||||
| 			}, | ||||
| 			ShouldErr: true, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When second argument is wrong", | ||||
| 			Expected: values.None, | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewCurrentDateTime(), | ||||
| 				values.NewInt(0), | ||||
| 			}, | ||||
| 			ShouldErr: true, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When DefaultTimeLayout", | ||||
| 			Expected: values.NewString("1999-02-07T15:04:05Z"), | ||||
| 			Args: []core.Value{ | ||||
| 				mustDefaultLayoutDt("1999-02-07T15:04:05Z"), | ||||
| 				values.NewString(values.DefaultTimeLayout), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name: "When RFC3339Nano", | ||||
| 			Expected: values.NewString( | ||||
| 				time.Date(2018, time.November, 5, 0, 54, 15, 5125, time.Local). | ||||
| 					Format(time.RFC3339Nano), | ||||
| 			), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime( | ||||
| 					time.Date(2018, time.November, 5, 0, 54, 15, 5125, time.Local), | ||||
| 				), | ||||
| 				values.NewString(time.RFC3339Nano), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name: "When custom format", | ||||
| 			Expected: values.NewString( | ||||
| 				time.Date(2018, time.November, 5, 0, 54, 15, 5125, time.Local). | ||||
| 					Format("2006-01-02"), | ||||
| 			), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime( | ||||
| 					time.Date(2018, time.November, 5, 0, 54, 15, 5125, time.Local), | ||||
| 				), | ||||
| 				values.NewString("2006-01-02"), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When empty string", | ||||
| 			Expected: values.NewString(""), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewCurrentDateTime(), | ||||
| 				values.NewString(""), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When random string without numbers", | ||||
| 			Expected: values.NewString("qwerty"), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewCurrentDateTime(), | ||||
| 				values.NewString("qwerty"), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When random string with numbers", | ||||
| 			Expected: values.NewString("qwerty2018uio"), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime( | ||||
| 					time.Date(2018, time.November, 5, 0, 54, 15, 5125, time.Local), | ||||
| 				), | ||||
| 				values.NewString("qwerty2006uio"), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateFormat) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										31
									
								
								pkg/stdlib/datetime/leapyear.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								pkg/stdlib/datetime/leapyear.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // DateLeapYear returns true if date is in a leap year else false. | ||||
| // @params date (DateTime) - source DateTime. | ||||
| // @return (Boolean) - date is in a leap year. | ||||
| func DateLeapYear(_ 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.NewBoolean(isLeap(year)), nil | ||||
| } | ||||
|  | ||||
| func isLeap(year int) bool { | ||||
| 	return year%4 == 0 && (year%100 != 0 || year%400 == 0) | ||||
| } | ||||
							
								
								
									
										43
									
								
								pkg/stdlib/datetime/leapyear_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/stdlib/datetime/leapyear_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 TestDateLeapYear(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 not a leap year", | ||||
| 			Expected: values.NewBoolean(false), | ||||
| 			Args:     []core.Value{mustDefaultLayoutDt("1999-02-07T15:04:05Z")}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When a leap year", | ||||
| 			Expected: values.NewBoolean(true), | ||||
| 			Args:     []core.Value{mustDefaultLayoutDt("1972-12-07T15:04:05Z")}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateLeapYear) | ||||
| 	} | ||||
| } | ||||
| @@ -4,14 +4,20 @@ import "github.com/MontFerret/ferret/pkg/runtime/core" | ||||
|  | ||||
| func NewLib() map[string]core.Function { | ||||
| 	return map[string]core.Function{ | ||||
| 		"NOW":            Now, | ||||
| 		"DATE":           Date, | ||||
| 		"DATE_DAYOFWEEK": DateDayOfWeek, | ||||
| 		"DATE_YEAR":      DateYear, | ||||
| 		"DATE_MONTH":     DateMonth, | ||||
| 		"DATE_DAY":       DateDay, | ||||
| 		"DATE_HOUR":      DateHour, | ||||
| 		"DATE_MINUTE":    DateMinute, | ||||
| 		"DATE_SECOND":    DateSecond, | ||||
| 		"NOW":                Now, | ||||
| 		"DATE":               Date, | ||||
| 		"DATE_DAYOFWEEK":     DateDayOfWeek, | ||||
| 		"DATE_YEAR":          DateYear, | ||||
| 		"DATE_MONTH":         DateMonth, | ||||
| 		"DATE_DAY":           DateDay, | ||||
| 		"DATE_HOUR":          DateHour, | ||||
| 		"DATE_MINUTE":        DateMinute, | ||||
| 		"DATE_SECOND":        DateSecond, | ||||
| 		"DATE_MILLISECOND":   DateMillisecond, | ||||
| 		"DATE_DAYOFYEAR":     DateDayOfYear, | ||||
| 		"DATE_LEAPYEAR":      DateLeapYear, | ||||
| 		"DATE_QUARTER":       DateQuarter, | ||||
| 		"DATE_DAYS_IN_MONTH": DateDaysInMonth, | ||||
| 		"DATE_FORMAT":        DateFormat, | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								pkg/stdlib/datetime/millisecond.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								pkg/stdlib/datetime/millisecond.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" | ||||
| ) | ||||
|  | ||||
| // DateMillisecond returns the millisecond of date as a number. | ||||
| // @params date (DateTime) - source DateTime. | ||||
| // @return (Int) - a millisecond number. | ||||
| func DateMillisecond(_ 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 | ||||
| 	} | ||||
|  | ||||
| 	msec := args[0].(values.DateTime).Nanosecond() / 1000000 | ||||
|  | ||||
| 	return values.NewInt(msec), nil | ||||
| } | ||||
							
								
								
									
										54
									
								
								pkg/stdlib/datetime/millisecond_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								pkg/stdlib/datetime/millisecond_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| package datetime_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/datetime" | ||||
| ) | ||||
|  | ||||
| func TestDateMillisecond(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 129 millisecond", | ||||
| 			Expected: values.NewInt(129), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(2018, 11, 4, 17, 3, 12, 129410001, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 		&testCase{ | ||||
| 			Name:     "When 0 milliseconds [0]", | ||||
| 			Expected: values.NewInt(0), | ||||
| 			Args:     []core.Value{mustDefaultLayoutDt("1629-02-28T15:59:59Z")}, | ||||
| 		}, | ||||
| 		// any nanosec < 1000000 equal to 0 milliseconds | ||||
| 		&testCase{ | ||||
| 			Name:     "When 0 milliseconds [1]", | ||||
| 			Expected: values.NewInt(0), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(0, 0, 0, 0, 0, 0, 999999, time.Local)), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateMillisecond) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										38
									
								
								pkg/stdlib/datetime/quarter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								pkg/stdlib/datetime/quarter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // DateQuarter returns which quarter date belongs to. | ||||
| // @params date (DateTime) - source DateTime. | ||||
| // @return (Int) - a quarter number. | ||||
| func DateQuarter(_ 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 | ||||
| 	} | ||||
|  | ||||
| 	month := args[0].(values.DateTime).Month() | ||||
| 	quarter := values.NewInt(1) | ||||
|  | ||||
| 	switch month { | ||||
| 	case time.April, time.May, time.June: | ||||
| 		quarter = values.NewInt(2) | ||||
| 	case time.July, time.August, time.September: | ||||
| 		quarter = values.NewInt(3) | ||||
| 	case time.October, time.November, time.December: | ||||
| 		quarter = values.NewInt(4) | ||||
| 	} | ||||
|  | ||||
| 	return quarter, nil | ||||
| } | ||||
							
								
								
									
										44
									
								
								pkg/stdlib/datetime/quarter_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/stdlib/datetime/quarter_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package datetime_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/datetime" | ||||
| ) | ||||
|  | ||||
| func TestDateQuarter(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, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for month := time.January; month <= time.December; month++ { | ||||
| 		tcs = append(tcs, &testCase{ | ||||
| 			Name:     "When " + month.String(), | ||||
| 			Expected: values.NewInt(((int(month) - 1) / 3) + 1), | ||||
| 			Args: []core.Value{ | ||||
| 				values.NewDateTime(time.Date(1999, month, 1, 1, 1, 1, 1, time.Local)), | ||||
| 			}, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range tcs { | ||||
| 		tc.Do(t, datetime.DateQuarter) | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user