Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended times lib functionality #374

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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: 3 additions & 0 deletions docs/stdlib-times.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ times := import("times")
2006" would be interpreted if it were the value; it serves as an example of
the input format. The same interpretation will then be made to the input
string.
- `parseInLocation(format string, s string, loc string)`: parseInLocation is like parse but parse interprets a time as UTC; parseInLocation interprets the time as in the given location.
vereecw marked this conversation as resolved.
Show resolved Hide resolved
vereecw marked this conversation as resolved.
Show resolved Hide resolved
- `unix(sec int, nsec int) => time`: returns the local Time corresponding to
the given Unix time, sec seconds and nsec nanoseconds since January 1,
1970 UTC.
Expand All @@ -88,6 +89,7 @@ times := import("times")
- `time_month(t time) => int`: returns the month of the year specified by t.
- `time_day(t time) => int`: returns the day of the month specified by t.
- `time_weekday(t time) => int`: returns the day of the week specified by t.
- `time_yearday(t time) => int`: returns the day of the year specified by t, in the range [1,365] for non-leap years, and [1,366] in leap years.
- `time_hour(t time) => int`: returns the hour within the day specified by t,
in the range [0, 23].
- `time_minute(t time) => int`: returns the minute offset within the hour
Expand All @@ -114,6 +116,7 @@ times := import("times")
t.
- `time_string(t time) => string`: returns the time formatted using the format
string "2006-01-02 15:04:05.999999999 -0700 MST".
- `to_location(t time, loc string)`: returns a copy of t representing the same time instant, but with the copy's location information set to loc for display purposes.
- `is_zero(t time) => bool`: reports whether t represents the zero time
instant, January 1, year 1, 00:00:00 UTC.
- `to_local(t time) => time`: returns t with the location set to local time.
Expand Down
123 changes: 123 additions & 0 deletions stdlib/times.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ var timesModule = map[string]tengo.Object{
Name: "parse",
Value: timesParse,
}, // parse(format, str) => time
"parseInLocation": &tengo.UserFunction{
Name: "parseInLocation",
Value: timesParseInLocation,
}, // parseInLocation(format, str, location) => time
"unix": &tengo.UserFunction{
Name: "unix",
Value: timesUnix,
Expand Down Expand Up @@ -132,6 +136,10 @@ var timesModule = map[string]tengo.Object{
Name: "time_weekday",
Value: timesTimeWeekday,
}, // time_weekday(time) => int
"time_yearday": &tengo.UserFunction{
Name: "time_yearday",
Value: timesTimeYearday,
}, // time_yearday(time) => int
"time_hour": &tengo.UserFunction{
Name: "time_hour",
Value: timesTimeHour,
Expand Down Expand Up @@ -168,6 +176,10 @@ var timesModule = map[string]tengo.Object{
Name: "time_string",
Value: timesTimeString,
}, // time_string(time) => string
"to_location": &tengo.UserFunction{
Name: "to_location",
Value: timesToLocation,
}, // to_location(time, location) => time
"is_zero": &tengo.UserFunction{
Name: "is_zero",
Value: timesIsZero,
Expand Down Expand Up @@ -555,6 +567,59 @@ func timesParse(args ...tengo.Object) (ret tengo.Object, err error) {
return
}

func timesParseInLocation(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 3 {
err = tengo.ErrWrongNumArguments
return
}

s1, ok := tengo.ToString(args[0])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
}
return
}

s2, ok := tengo.ToString(args[1])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "second",
Expected: "string(compatible)",
Found: args[1].TypeName(),
}
return
}

s3, ok := tengo.ToString(args[2])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "third",
Expected: "string(compatible)",
Found: args[2].TypeName(),
}
return
}

location, err := time.LoadLocation(s3)
if err != nil {
ret = wrapError(err)
return
}

parsed, err := time.ParseInLocation(s1, s2, location)
if err != nil {
ret = wrapError(err)
return
}

ret = &tengo.Time{Value: parsed}

return
}

func timesUnix(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 2 {
err = tengo.ErrWrongNumArguments
Expand Down Expand Up @@ -853,6 +918,27 @@ func timesTimeWeekday(args ...tengo.Object) (ret tengo.Object, err error) {
return
}

func timesTimeYearday(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 1 {
err = tengo.ErrWrongNumArguments
return
}

t1, ok := tengo.ToTime(args[0])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "time(compatible)",
Found: args[0].TypeName(),
}
return
}

ret = &tengo.Int{Value: int64(t1.YearDay())}

return
}

func timesTimeHour(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 1 {
err = tengo.ErrWrongNumArguments
Expand Down Expand Up @@ -1022,6 +1108,43 @@ func timesTimeFormat(args ...tengo.Object) (ret tengo.Object, err error) {
return
}

func timesToLocation(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 2 {
err = tengo.ErrWrongNumArguments
return
}

t1, ok := tengo.ToTime(args[0])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "time(compatible)",
Found: args[0].TypeName(),
}
return
}

s2, ok := tengo.ToString(args[1])
if !ok {
err = tengo.ErrInvalidArgumentType{
Name: "second",
Expected: "string(compatible)",
Found: args[1].TypeName(),
}
return
}

location, err := time.LoadLocation(s2)
if err != nil {
ret = wrapError(err)
return
}

ret = &tengo.Time{Value: t1.In(location)}

return
}

func timesIsZero(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 1 {
err = tengo.ErrWrongNumArguments
Expand Down
7 changes: 7 additions & 0 deletions stdlib/times_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func TestTimes(t *testing.T) {
module(t, "times").
call("parse", time.RFC3339, "1982-09-28T19:21:44+07:00").
expect(parsed)
module(t, "times").
call("parseInLocation", time.RFC3339, "1982-09-28T19:21:44+07:00", "America/Los_Angeles").
expect(parsed)
module(t, "times").
call("unix", 1234325, 94493).
expect(time.Unix(1234325, 94493))
Expand Down Expand Up @@ -80,4 +83,8 @@ func TestTimes(t *testing.T) {
module(t, "times").call("time_location", time1).
expect(time1.Location().String())
module(t, "times").call("time_string", time1).expect(time1.String())
location, _ := time.LoadLocation("America/Los_Angeles")
module(t, "times").call("to_location", time1, "America/Los_Angeles").expect(time1.In(location))
module(t, "times").call("time_location", time1.In(location)).expect("America/Los_Angeles")
module(t, "times").call("to_location", time1, "invalid location name").expectError()
}