Better support for TZ locations in the times module (#397)
* Handle panics by deferring recover as an error * Check for type in recover handler * Added support for times.in_location * Added support for location (TZ) to times.date * Updated documentation
This commit is contained in:
parent
ecc3d9181e
commit
82b543fd98
3 changed files with 79 additions and 5 deletions
|
@ -62,9 +62,10 @@ times := import("times")
|
|||
duration.
|
||||
- `month_string(month int) => string`: returns the English name of the month
|
||||
("January", "February", ...).
|
||||
- `date(year int, month int, day int, hour int, min int, sec int, nsec int) => time`:
|
||||
returns the Time corresponding to "yyyy-mm-dd hh:mm:ss + nsec nanoseconds".
|
||||
Current location is used.
|
||||
- `date(year int, month int, day int, hour int, min int, sec int, nsec int, loc string) => time`:
|
||||
returns the Time corresponding to "yyyy-mm-dd hh:mm:ss + nsec nanoseconds" in
|
||||
the appropriate zone for that Time in the given (optional) location.
|
||||
The Local time zone will be used if executed without specifying a location.
|
||||
- `now() => time`: returns the current local time.
|
||||
- `parse(format string, s string) => time`: parses a formatted string and
|
||||
returns the time value it represents. The layout defines the format by
|
||||
|
@ -116,5 +117,8 @@ times := import("times")
|
|||
string "2006-01-02 15:04:05.999999999 -0700 MST".
|
||||
- `is_zero(t time) => bool`: reports whether t represents the zero time
|
||||
instant, January 1, year 1, 00:00:00 UTC.
|
||||
- `in_location(t time, l string) => time`: returns a copy of t representing
|
||||
the same time instant, but with the copy's location information set to l for
|
||||
display purposes.
|
||||
- `to_local(t time) => time`: returns t with the location set to local time.
|
||||
- `to_utc(t time) => time`: returns t with the location set to UTC.
|
||||
|
|
|
@ -180,6 +180,10 @@ var timesModule = map[string]tengo.Object{
|
|||
Name: "to_utc",
|
||||
Value: timesToUTC,
|
||||
}, // to_utc(time) => time
|
||||
"in_location": &tengo.UserFunction{
|
||||
Name: "in_location",
|
||||
Value: timesInLocation,
|
||||
}, // in_location(time, location) => time
|
||||
}
|
||||
|
||||
func timesSleep(args ...tengo.Object) (ret tengo.Object, err error) {
|
||||
|
@ -430,7 +434,7 @@ func timesDate(args ...tengo.Object) (
|
|||
ret tengo.Object,
|
||||
err error,
|
||||
) {
|
||||
if len(args) != 7 {
|
||||
if len(args) < 7 || len(args) > 8 {
|
||||
err = tengo.ErrWrongNumArguments
|
||||
return
|
||||
}
|
||||
|
@ -499,9 +503,29 @@ func timesDate(args ...tengo.Object) (
|
|||
return
|
||||
}
|
||||
|
||||
var loc *time.Location
|
||||
if len(args) == 8 {
|
||||
i8, ok := tengo.ToString(args[7])
|
||||
if !ok {
|
||||
err = tengo.ErrInvalidArgumentType{
|
||||
Name: "eighth",
|
||||
Expected: "string(compatible)",
|
||||
Found: args[7].TypeName(),
|
||||
}
|
||||
return
|
||||
}
|
||||
loc, err = time.LoadLocation(i8)
|
||||
if err != nil {
|
||||
ret = wrapError(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
loc = time.Now().Location()
|
||||
}
|
||||
|
||||
ret = &tengo.Time{
|
||||
Value: time.Date(i1,
|
||||
time.Month(i2), i3, i4, i5, i6, i7, time.Now().Location()),
|
||||
time.Month(i2), i3, i4, i5, i6, i7, loc),
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -1113,6 +1137,46 @@ func timesTimeLocation(args ...tengo.Object) (
|
|||
return
|
||||
}
|
||||
|
||||
func timesInLocation(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 timesTimeString(args ...tengo.Object) (ret tengo.Object, err error) {
|
||||
if len(args) != 1 {
|
||||
err = tengo.ErrWrongNumArguments
|
||||
|
|
|
@ -11,6 +11,8 @@ import (
|
|||
func TestTimes(t *testing.T) {
|
||||
time1 := time.Date(1982, 9, 28, 19, 21, 44, 999, time.Now().Location())
|
||||
time2 := time.Now()
|
||||
location, _ := time.LoadLocation("Pacific/Auckland")
|
||||
time3 := time.Date(1982, 9, 28, 19, 21, 44, 999, location)
|
||||
|
||||
module(t, "times").call("sleep", 1).expect(tengo.UndefinedValue)
|
||||
|
||||
|
@ -35,6 +37,9 @@ func TestTimes(t *testing.T) {
|
|||
|
||||
module(t, "times").call("date", 1982, 9, 28, 19, 21, 44, 999).
|
||||
expect(time1)
|
||||
module(t, "times").call("date", 1982, 9, 28, 19, 21, 44, 999, "Pacific/Auckland").
|
||||
expect(time3)
|
||||
|
||||
nowD := time.Until(module(t, "times").call("now").
|
||||
o.(*tengo.Time).Value).Nanoseconds()
|
||||
require.True(t, 0 > nowD && nowD > -100000000) // within 100ms
|
||||
|
@ -80,4 +85,5 @@ 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())
|
||||
module(t, "times").call("in_location", time1, location.String()).expect(time1.In(location))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue