Skip to content

Commit 1a8bb0c

Browse files
committed
time: Applied remarks
1 parent a4a3b8a commit 1a8bb0c

File tree

2 files changed

+43
-47
lines changed

2 files changed

+43
-47
lines changed

lib/time/time.go

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package time
22

33
import (
4-
"errors"
54
"fmt"
65
"sort"
76
"time"
@@ -15,12 +14,12 @@ import (
1514
var Module = &starlarkstruct.Module{
1615
Name: "time",
1716
Members: starlark.StringDict{
18-
"parse_duration": starlark.NewBuiltin("parse_duration", parseDuration),
19-
"parse_location": starlark.NewBuiltin("parse_location", parseLocation),
20-
"now": starlark.NewBuiltin("now", now),
21-
"time": starlark.NewBuiltin("time", newTime),
22-
"parse_time": starlark.NewBuiltin("time", parseTime),
23-
"from_timestamp": starlark.NewBuiltin("from_timestamp", fromTimestamp),
17+
"parse_duration": starlark.NewBuiltin("parse_duration", parseDuration),
18+
"is_valid_timezone": starlark.NewBuiltin("is_valid_timezone", isValidTimezone),
19+
"now": starlark.NewBuiltin("now", now),
20+
"time": starlark.NewBuiltin("time", newTime),
21+
"parse_time": starlark.NewBuiltin("parse_time", parseTime),
22+
"from_timestamp": starlark.NewBuiltin("from_timestamp", fromTimestamp),
2423

2524
"nanosecond": Duration(time.Nanosecond),
2625
"microsecond": Duration(time.Microsecond),
@@ -36,35 +35,42 @@ var Module = &starlarkstruct.Module{
3635
// Starlark scripts to be fully deterministic.
3736
var NowFunc = time.Now
3837

38+
// Parses the given duration string.
39+
// A duration string is a possibly signed sequence of
40+
// decimal numbers, each with optional fraction and a unit suffix,
41+
// such as "300ms", "-1.5h" or "2h45m".
42+
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
3943
func parseDuration(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
4044
var d Duration
4145
err := starlark.UnpackPositionalArgs("duration", args, kwargs, 1, &d)
4246
return d, err
4347
}
4448

45-
func parseLocation(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
49+
// Indicates whether the given name of location is valid or not.
50+
// Returns true if it is valid, false otherwise.
51+
func isValidTimezone(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
4652
var s string
47-
if err := starlark.UnpackPositionalArgs("location", args, kwargs, 1, &s); err != nil {
53+
if err := starlark.UnpackPositionalArgs("is_valid_timezone", args, kwargs, 1, &s); err != nil {
4854
return nil, err
4955
}
50-
loc, err := time.LoadLocation(s)
51-
if err != nil {
52-
return nil, err
53-
}
54-
55-
return starlark.String(loc.String()), nil
56+
_, err := time.LoadLocation(s)
57+
return starlark.Bool(err == nil), nil
5658
}
5759

60+
// The expected arguments are a time string (mandatory), a time format (optional by default it is RFC3339)
61+
// and a name of location (optional by default is UTC).
62+
// Parses the given time string using a specific time format and location.
5863
func parseTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
5964
var (
60-
x, location string
61-
format = time.RFC3339
65+
x string
66+
location = "UTC"
67+
format = time.RFC3339
6268
)
6369
if err := starlark.UnpackArgs("time", args, kwargs, "x", &x, "format?", &format, "location?", &location); err != nil {
6470
return nil, err
6571
}
6672

67-
if location == "" {
73+
if location == "UTC" {
6874
t, err := time.Parse(format, x)
6975
if err != nil {
7076
return nil, err
@@ -83,6 +89,8 @@ func parseTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple
8389
return Time(t), nil
8490
}
8591

92+
// Parses the given timestamp string corresponding to
93+
// the total amount of seconds since January 1, 1970 UTC.
8694
func fromTimestamp(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
8795
var x int64
8896
if err := starlark.UnpackPositionalArgs("from_timestamp", args, kwargs, 1, &x); err != nil {
@@ -91,14 +99,15 @@ func fromTimestamp(thread *starlark.Thread, _ *starlark.Builtin, args starlark.T
9199
return Time(time.Unix(x, 0)), nil
92100
}
93101

102+
// Generates the current time current time.
94103
func now(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
95104
return Time(NowFunc()), nil
96105
}
97106

98107
// Duration is a Starlark representation of a duration.
99108
type Duration time.Duration
100109

101-
// assert at compile time that Duration implements Unpacker.
110+
// Assert at compile time that Duration implements Unpacker.
102111
var _ starlark.Unpacker = (*Duration)(nil)
103112

104113
// Unpack is a custom argument unpacker
@@ -191,7 +200,7 @@ func (d Duration) CompareSameType(op syntax.Token, v starlark.Value, depth int)
191200
case syntax.GE:
192201
return x >= y, nil
193202
}
194-
return false, errors.New("operation not supported")
203+
return threeway(op, x-y), nil
195204
}
196205

197206
// Binary implements binary operators, which satisfies the starlark.HasBinary
@@ -203,7 +212,6 @@ func (d Duration) CompareSameType(op syntax.Token, v starlark.Value, depth int)
203212
// duration / int = duration
204213
// duration / float = duration
205214
// duration // duration = int
206-
// duration // int = duration
207215
// duration * int = duration
208216
func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side) (starlark.Value, error) {
209217
x := time.Duration(d)
@@ -226,10 +234,10 @@ func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side)
226234
case syntax.SLASH:
227235
switch y := y.(type) {
228236
case Duration:
229-
if int64(y) == 0 {
237+
if y == 0 {
230238
return nil, fmt.Errorf("%s division by zero", d.Type())
231239
}
232-
return starlark.Float(float64(x.Nanoseconds()) / float64(time.Duration(y).Nanoseconds())), nil
240+
return starlark.Float(x.Nanoseconds()) / starlark.Float(time.Duration(y).Nanoseconds()), nil
233241
case starlark.Int:
234242
if side == starlark.Right {
235243
return nil, fmt.Errorf("unsupported operation")
@@ -238,10 +246,10 @@ func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side)
238246
if !ok {
239247
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
240248
}
241-
if int64(i) == 0 {
249+
if i == 0 {
242250
return nil, fmt.Errorf("%s division by zero", d.Type())
243251
}
244-
return Duration(x.Nanoseconds() / i), nil
252+
return d / Duration(i), nil
245253
case starlark.Float:
246254
f := float64(y)
247255
if f == 0 {
@@ -253,22 +261,10 @@ func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side)
253261
case syntax.SLASHSLASH:
254262
switch y := y.(type) {
255263
case Duration:
256-
if int64(y) == 0 {
264+
if y == 0 {
257265
return nil, fmt.Errorf("%s division by zero", d.Type())
258266
}
259267
return starlark.MakeInt64(x.Nanoseconds() / time.Duration(y).Nanoseconds()), nil
260-
case starlark.Int:
261-
if side == starlark.Right {
262-
return nil, fmt.Errorf("unsupported operation")
263-
}
264-
i, ok := y.Int64()
265-
if !ok {
266-
return nil, fmt.Errorf("int value out of range (want signed 64-bit value)")
267-
}
268-
if int64(i) == 0 {
269-
return nil, fmt.Errorf("%s division by zero", d.Type())
270-
}
271-
return d / Duration(i), nil
272268
}
273269

274270
case syntax.STAR:
@@ -285,7 +281,7 @@ func (d Duration) Binary(op syntax.Token, y starlark.Value, side starlark.Side)
285281
return nil, nil
286282
}
287283

288-
// Time is a starlark representation of a moment in time.
284+
// Time is a Starlark representation of a moment in time.
289285
type Time time.Time
290286

291287
func newTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
@@ -316,7 +312,7 @@ func newTime(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple,
316312
}
317313

318314
// String returns the time formatted using the format string
319-
// "2006-01-02 15:04:05.999999999 -0700 MST"
315+
// "2006-01-02 15:04:05.999999999 -0700 MST".
320316
func (t Time) String() string { return time.Time(t).String() }
321317

322318
// Type returns "time.time".
@@ -472,7 +468,7 @@ func builtinAttrNames(methods map[string]builtinMethod) []string {
472468
return names
473469
}
474470

475-
// threeway interprets a three-way comparison value cmp (-1, 0, +1)
471+
// Threeway interprets a three-way comparison value cmp (-1, 0, +1)
476472
// as a boolean comparison (e.g. x < y).
477473
func threeway(op syntax.Token, cmp int) bool {
478474
switch op {

starlark/testdata/time.star

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,22 @@ assert.fails(lambda: d10h / 0.0, "division by zero")
8686
# duration // duration = int
8787
assert.eq(d10h // time.parse_duration("16m"), 37)
8888
assert.fails(lambda: d10h // time.parse_duration("0"), "division by zero")
89-
# duration // int = duration
90-
assert.eq(d10h // 20, time.parse_duration("30m"))
91-
assert.fails(lambda: d10h // 0, "division by zero")
92-
# int // duration = error
93-
assert.fails(lambda: 20 // d10h, "unsupported operation")
9489
# duration * int = duration
9590
assert.eq(d1s * 1000, time.parse_duration("16m40s"))
96-
assert.fails(lambda: d10h // 0, "division by zero")
9791
# int * duration = duration
9892
assert.eq(1000 * d1s, time.parse_duration("16m40s"))
9993

94+
# is_valid_timezone(location)
95+
assert.true(time.is_valid_timezone("UTC"))
96+
assert.true(time.is_valid_timezone("US/Eastern"))
97+
assert.true(not time.is_valid_timezone("UKN"))
98+
10099
# time(year=..., month=..., day=..., hour=..., minute=..., second=..., nanosecond=..., location=...)
101100
assert.fails(lambda: time.time(2009, 6, 12, 12, 6, 10, 99, "US/Eastern"), "unexpected positional argument")
102101
t1 = time.time(year=2009, month=6, day=12, hour=12, minute=6, second=10, nanosecond=99, location="US/Eastern")
103102
assert.eq(t1, time.parse_time("2009-06-12T12:06:10.000000099", format="2006-01-02T15:04:05.999999999", location="US/Eastern"))
104103
assert.eq(time.time(year=2012, month=12, day=31), time.parse_time("2012-12-31T00:00:00Z"))
104+
assert.eq(time.time(year=2009, month=6, day=12, hour=12, minute=6, second=10, nanosecond=99, location="UTC"), time.time(year=2009, month=6, day=12, hour=12, minute=6, second=10, nanosecond=99))
105105

106106
# time attributes
107107
assert.eq(2009, t1.year)

0 commit comments

Comments
 (0)