-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtime.go
More file actions
127 lines (104 loc) · 3.35 KB
/
Copy pathtime.go
File metadata and controls
127 lines (104 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package glerp
import (
"fmt"
"time"
)
// timeBuiltins returns Go-backed time procedures, registered as the
// "go/time" builtin library in StandardLibraries.
func timeBuiltins() map[string]BuiltinFn {
return map[string]BuiltinFn{
"current-second": builtinCurrentSecond,
"current-jiffy": builtinCurrentJiffy,
"time-make": builtinTimeMake,
"time-components": builtinTimeComponents,
"time-format": builtinTimeFormat,
"time-parse": builtinTimeParse,
}
}
func builtinCurrentSecond(args []Expr) (Expr, error) {
if len(args) != 0 {
return nil, fmt.Errorf("current-second: expected 0 arguments, got %d", len(args))
}
return num(float64(time.Now().UnixNano()) / 1e9), nil
}
func builtinCurrentJiffy(args []Expr) (Expr, error) {
if len(args) != 0 {
return nil, fmt.Errorf("current-jiffy: expected 0 arguments, got %d", len(args))
}
return num(float64(time.Now().UnixNano())), nil
}
// builtinTimeMake constructs a UTC time from (year month day hour minute second)
// and returns it as a unix timestamp (float64 seconds).
func builtinTimeMake(args []Expr) (Expr, error) {
if len(args) != 6 {
return nil, fmt.Errorf("time-make: expected 6 arguments, got %d", len(args))
}
vals := make([]int, 6)
for i, a := range args {
n, err := toNum("time-make", a)
if err != nil {
return nil, err
}
vals[i] = int(n)
}
t := time.Date(vals[0], time.Month(vals[1]), vals[2], vals[3], vals[4], vals[5], 0, time.UTC)
return num(float64(t.Unix())), nil
}
// builtinTimeComponents returns (year month day hour minute second weekday) for
// a unix timestamp. weekday is 0 (Sunday) through 6 (Saturday).
func builtinTimeComponents(args []Expr) (Expr, error) {
if len(args) != 1 {
return nil, fmt.Errorf("time-components: expected 1 argument, got %d", len(args))
}
ts, err := toNum("time-components", args[0])
if err != nil {
return nil, err
}
sec := int64(ts)
nsec := int64((ts - float64(sec)) * 1e9)
t := time.Unix(sec, nsec).UTC()
return builtinList([]Expr{
num(float64(t.Year())),
num(float64(t.Month())),
num(float64(t.Day())),
num(float64(t.Hour())),
num(float64(t.Minute())),
num(float64(t.Second())),
num(float64(t.Weekday())),
})
}
// builtinTimeFormat formats a unix timestamp using a Go reference-time layout string.
func builtinTimeFormat(args []Expr) (Expr, error) {
if len(args) != 2 {
return nil, fmt.Errorf("time-format: expected 2 arguments, got %d", len(args))
}
ts, err := toNum("time-format", args[0])
if err != nil {
return nil, err
}
layout, ok := args[1].(*StringExpr)
if !ok {
return nil, fmt.Errorf("time-format: layout must be a string, got %s", args[1].String())
}
sec := int64(ts)
nsec := int64((ts - float64(sec)) * 1e9)
t := time.Unix(sec, nsec).UTC()
return &StringExpr{val: t.Format(layout.val)}, nil
}
// builtinTimeParse parses a time string using a Go reference-time layout and
// returns a unix timestamp (float64 seconds).
func builtinTimeParse(args []Expr) (Expr, error) {
if len(args) != 2 {
return nil, fmt.Errorf("time-parse: expected 2 arguments, got %d", len(args))
}
layout, ok1 := args[0].(*StringExpr)
value, ok2 := args[1].(*StringExpr)
if !ok1 || !ok2 {
return nil, fmt.Errorf("time-parse: both arguments must be strings")
}
t, err := time.Parse(layout.val, value.val)
if err != nil {
return nil, fmt.Errorf("time-parse: %w", err)
}
return num(float64(t.Unix())), nil
}