gofront 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/package.json +5 -4
- package/src/backend/js/expressions.js +849 -371
- package/src/backend/js/index.js +241 -147
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +512 -2547
- package/src/backend/js/statements.js +506 -103
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +177 -13
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +63 -171
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +643 -256
- package/src/backend/wasm/emit-exprs.js +124 -57
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-stmts.js +325 -75
- package/src/backend/wasm/emit.js +104 -13
- package/src/backend/wasm/globals.js +47 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +36 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +92 -717
- package/src/backend/wasm/monomorph.js +103 -6
- package/src/backend/wasm/natives.js +596 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +68 -20
- package/src/backend/wasm/variadic.js +3 -3
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +108 -130
- package/src/lexer/lexer.js +105 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +354 -132
- package/src/link/type-names.js +148 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +32 -3
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +905 -0
- package/src/lower/functions.js +2 -0
- package/src/lower/gen-types.js +274 -0
- package/src/lower/index.js +7 -1
- package/src/lower/json-codecs.js +228 -247
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +28 -5
- package/src/parser/expressions.js +86 -16
- package/src/parser/statements.js +1 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +1 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +124 -11
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +32 -6
- package/src/typechecker/expressions.js +326 -98
- package/src/typechecker/index.js +208 -33
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +40 -0
- package/src/typechecker/resolve.js +192 -36
- package/src/typechecker/statements.js +122 -11
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +203 -573
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +391 -452
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +235 -50
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Copyright 2009 The Go Authors. All rights reserved.
|
|
6
|
+
// Use of this source code is governed by a BSD-style
|
|
7
|
+
// license that can be found in the LICENSE file.
|
|
8
|
+
|
|
9
|
+
// Package time provides functionality for measuring and displaying time.
|
|
10
|
+
//
|
|
11
|
+
// A Time is an instant with nanosecond precision and a Location; there is no
|
|
12
|
+
// monotonic clock reading, so Since and Sub compare wall clock times. The
|
|
13
|
+
// Local location is the host's time zone. Sleep, AfterFunc and Timer are
|
|
14
|
+
// part of the JavaScript-only part of the package.
|
|
15
|
+
package time
|
|
16
|
+
|
|
17
|
+
// A Month specifies a month of the year (January = 1, ...).
|
|
18
|
+
type Month int
|
|
19
|
+
|
|
20
|
+
const (
|
|
21
|
+
January Month = 1 + iota
|
|
22
|
+
February
|
|
23
|
+
March
|
|
24
|
+
April
|
|
25
|
+
May
|
|
26
|
+
June
|
|
27
|
+
July
|
|
28
|
+
August
|
|
29
|
+
September
|
|
30
|
+
October
|
|
31
|
+
November
|
|
32
|
+
December
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
var longMonthNames = []string{
|
|
36
|
+
"January",
|
|
37
|
+
"February",
|
|
38
|
+
"March",
|
|
39
|
+
"April",
|
|
40
|
+
"May",
|
|
41
|
+
"June",
|
|
42
|
+
"July",
|
|
43
|
+
"August",
|
|
44
|
+
"September",
|
|
45
|
+
"October",
|
|
46
|
+
"November",
|
|
47
|
+
"December",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// String returns the English name of the month ("January", "February", ...).
|
|
51
|
+
func (m Month) String() string {
|
|
52
|
+
if January <= m && m <= December {
|
|
53
|
+
return longMonthNames[m-1]
|
|
54
|
+
}
|
|
55
|
+
return "%!Month(" + itoa(int(m)) + ")"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// A Weekday specifies a day of the week (Sunday = 0, ...).
|
|
59
|
+
type Weekday int
|
|
60
|
+
|
|
61
|
+
const (
|
|
62
|
+
Sunday Weekday = iota
|
|
63
|
+
Monday
|
|
64
|
+
Tuesday
|
|
65
|
+
Wednesday
|
|
66
|
+
Thursday
|
|
67
|
+
Friday
|
|
68
|
+
Saturday
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
var longDayNames = []string{
|
|
72
|
+
"Sunday",
|
|
73
|
+
"Monday",
|
|
74
|
+
"Tuesday",
|
|
75
|
+
"Wednesday",
|
|
76
|
+
"Thursday",
|
|
77
|
+
"Friday",
|
|
78
|
+
"Saturday",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// String returns the English name of the day ("Sunday", "Monday", ...).
|
|
82
|
+
func (d Weekday) String() string {
|
|
83
|
+
if Sunday <= d && d <= Saturday {
|
|
84
|
+
return longDayNames[d]
|
|
85
|
+
}
|
|
86
|
+
return "%!Weekday(" + itoa(int(d)) + ")"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// itoa formats a decimal integer.
|
|
90
|
+
func itoa(v int) string {
|
|
91
|
+
if v == 0 {
|
|
92
|
+
return "0"
|
|
93
|
+
}
|
|
94
|
+
buf := make([]byte, 24)
|
|
95
|
+
w := len(buf)
|
|
96
|
+
neg := v < 0
|
|
97
|
+
u := uint64(v)
|
|
98
|
+
if neg {
|
|
99
|
+
u = -u
|
|
100
|
+
}
|
|
101
|
+
w = fmtInt(buf, w, u)
|
|
102
|
+
if neg {
|
|
103
|
+
w--
|
|
104
|
+
buf[w] = '-'
|
|
105
|
+
}
|
|
106
|
+
return string(buf[w:])
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// A Location maps time instants to the zone in use at that time. The
|
|
110
|
+
// predefined UTC and Local locations are the only ones with a name other
|
|
111
|
+
// than the one FixedZone was given.
|
|
112
|
+
type Location struct {
|
|
113
|
+
name string
|
|
114
|
+
offset int // seconds east of UTC, for a fixed zone
|
|
115
|
+
kind int
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const (
|
|
119
|
+
kindFixed = iota
|
|
120
|
+
kindUTC
|
|
121
|
+
kindLocal
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
// UTC represents Universal Coordinated Time (UTC).
|
|
125
|
+
var UTC *Location = &Location{name: "UTC", kind: kindUTC}
|
|
126
|
+
|
|
127
|
+
// Local represents the system's local time zone.
|
|
128
|
+
var Local *Location = &Location{name: "Local", kind: kindLocal}
|
|
129
|
+
|
|
130
|
+
// String returns a descriptive name for the time zone information.
|
|
131
|
+
func (l *Location) String() string {
|
|
132
|
+
if l == nil {
|
|
133
|
+
return "UTC"
|
|
134
|
+
}
|
|
135
|
+
return l.name
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// FixedZone returns a Location that always uses the given zone name and
|
|
139
|
+
// offset (seconds east of UTC).
|
|
140
|
+
func FixedZone(name string, offset int) *Location {
|
|
141
|
+
return &Location{name: name, offset: offset}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// hostNow returns the host clock as nanoseconds since the Unix epoch.
|
|
145
|
+
//
|
|
146
|
+
//gofront:intrinsic time_now
|
|
147
|
+
func hostNow() int64
|
|
148
|
+
|
|
149
|
+
// hostOffset returns the offset in seconds east of UTC of the host's time
|
|
150
|
+
// zone at the given Unix time.
|
|
151
|
+
//
|
|
152
|
+
//gofront:intrinsic time_zone_offset
|
|
153
|
+
func hostOffset(unix int64) int
|
|
154
|
+
|
|
155
|
+
// lookup returns the zone abbreviation and offset in effect at the given
|
|
156
|
+
// Unix time.
|
|
157
|
+
func lookupZone(l *Location, unix int64) (name string, offset int) {
|
|
158
|
+
if l == nil || l.kind == kindUTC {
|
|
159
|
+
return "UTC", 0
|
|
160
|
+
}
|
|
161
|
+
if l.kind == kindLocal {
|
|
162
|
+
off := hostOffset(unix)
|
|
163
|
+
if off == 0 {
|
|
164
|
+
return "UTC", 0
|
|
165
|
+
}
|
|
166
|
+
return "", off
|
|
167
|
+
}
|
|
168
|
+
return l.name, l.offset
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// A Time represents an instant in time with nanosecond precision.
|
|
172
|
+
//
|
|
173
|
+
// The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC.
|
|
174
|
+
// Programs using times should typically store and pass them as values, not
|
|
175
|
+
// pointers. Time values can be compared with Equal, Before and After; the ==
|
|
176
|
+
// operator also compares the Location pointer.
|
|
177
|
+
type Time struct {
|
|
178
|
+
sec int64 // seconds since January 1, year 1 00:00:00 UTC
|
|
179
|
+
nsec int32 // nanoseconds within the second, in [0, 999999999]
|
|
180
|
+
loc *Location
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const (
|
|
184
|
+
secondsPerMinute = 60
|
|
185
|
+
secondsPerHour = 60 * secondsPerMinute
|
|
186
|
+
secondsPerDay = 24 * secondsPerHour
|
|
187
|
+
secondsPerWeek = 7 * secondsPerDay
|
|
188
|
+
daysPer400Years = 365*400 + 97
|
|
189
|
+
daysPer100Years = 365*100 + 24
|
|
190
|
+
daysPer4Years = 365*4 + 1
|
|
191
|
+
|
|
192
|
+
// Seconds between January 1, year 1 and January 1, 1970.
|
|
193
|
+
unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
|
|
194
|
+
internalToUnix int64 = -unixToInternal
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
func (t Time) unixSec() int64 { return t.sec + internalToUnix }
|
|
198
|
+
|
|
199
|
+
// setLoc returns t in the location loc; the UTC location is stored as nil.
|
|
200
|
+
func (t Time) setLoc(loc *Location) Time {
|
|
201
|
+
if loc != nil && loc.kind == kindUTC {
|
|
202
|
+
loc = nil
|
|
203
|
+
}
|
|
204
|
+
t.loc = loc
|
|
205
|
+
return t
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// zone returns the zone abbreviation and offset in effect at t.
|
|
209
|
+
func (t Time) zone() (name string, offset int) {
|
|
210
|
+
return lookupZone(t.loc, t.unixSec())
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// abs returns the seconds since January 1, year 1 at t's location.
|
|
214
|
+
func (t Time) abs() int64 {
|
|
215
|
+
_, off := t.zone()
|
|
216
|
+
return t.sec + int64(off)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// floorDiv returns x/y rounded toward negative infinity (y > 0).
|
|
220
|
+
func floorDiv(x, y int64) int64 {
|
|
221
|
+
q := x / y
|
|
222
|
+
if x%y < 0 {
|
|
223
|
+
q--
|
|
224
|
+
}
|
|
225
|
+
return q
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// daysSinceEpoch returns the number of days between January 1, year 1 and
|
|
229
|
+
// January 1 of the given year.
|
|
230
|
+
func daysSinceEpoch(year int) int64 {
|
|
231
|
+
y := int64(year) - 1
|
|
232
|
+
n := floorDiv(y, 400)
|
|
233
|
+
y -= 400 * n
|
|
234
|
+
d := daysPer400Years * n
|
|
235
|
+
|
|
236
|
+
n = y / 100
|
|
237
|
+
y -= 100 * n
|
|
238
|
+
d += daysPer100Years * n
|
|
239
|
+
|
|
240
|
+
n = y / 4
|
|
241
|
+
y -= 4 * n
|
|
242
|
+
d += daysPer4Years * n
|
|
243
|
+
|
|
244
|
+
d += 365 * y
|
|
245
|
+
return d
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
func isLeap(year int) bool {
|
|
249
|
+
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// daysBefore[m] counts the number of days in a non-leap year before month m
|
|
253
|
+
// begins. There is an entry for m=12, counting the number of days before
|
|
254
|
+
// January of next year (365).
|
|
255
|
+
var daysBefore = [13]int{
|
|
256
|
+
0,
|
|
257
|
+
31,
|
|
258
|
+
31 + 28,
|
|
259
|
+
31 + 28 + 31,
|
|
260
|
+
31 + 28 + 31 + 30,
|
|
261
|
+
31 + 28 + 31 + 30 + 31,
|
|
262
|
+
31 + 28 + 31 + 30 + 31 + 30,
|
|
263
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31,
|
|
264
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
|
|
265
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
|
|
266
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
|
|
267
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
|
|
268
|
+
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// absDate splits seconds since January 1, year 1 into the calendar date; yday
|
|
272
|
+
// is the zero-based day of the year.
|
|
273
|
+
func absDate(abs int64) (year int, month Month, day int, yday int) {
|
|
274
|
+
d := floorDiv(abs, secondsPerDay)
|
|
275
|
+
|
|
276
|
+
// Account for 400 year cycles.
|
|
277
|
+
n := floorDiv(d, daysPer400Years)
|
|
278
|
+
y := 400 * n
|
|
279
|
+
c := int(d - daysPer400Years*n)
|
|
280
|
+
|
|
281
|
+
// Cut off 100-year cycles.
|
|
282
|
+
k := c / daysPer100Years
|
|
283
|
+
k -= k >> 2
|
|
284
|
+
y += int64(100 * k)
|
|
285
|
+
c -= daysPer100Years * k
|
|
286
|
+
|
|
287
|
+
// Cut off 4-year cycles.
|
|
288
|
+
k = c / daysPer4Years
|
|
289
|
+
y += int64(4 * k)
|
|
290
|
+
c -= daysPer4Years * k
|
|
291
|
+
|
|
292
|
+
// Cut off years within a 4-year cycle.
|
|
293
|
+
k = c / 365
|
|
294
|
+
k -= k >> 2
|
|
295
|
+
y += int64(k)
|
|
296
|
+
c -= 365 * k
|
|
297
|
+
|
|
298
|
+
year = int(y) + 1
|
|
299
|
+
yday = c
|
|
300
|
+
day = c
|
|
301
|
+
if isLeap(year) {
|
|
302
|
+
// Leap year: February 29 is day 59 (zero-based).
|
|
303
|
+
switch {
|
|
304
|
+
case day > 31+29-1:
|
|
305
|
+
// After leap day; pretend it wasn't there.
|
|
306
|
+
day--
|
|
307
|
+
case day == 31+29-1:
|
|
308
|
+
// Leap day.
|
|
309
|
+
return year, February, 29, yday
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Estimate month on assumption that every month has 31 days. The estimate
|
|
314
|
+
// may be too low by at most one month, so adjust.
|
|
315
|
+
m := day / 31
|
|
316
|
+
end := daysBefore[m+1]
|
|
317
|
+
var begin int
|
|
318
|
+
if day >= end {
|
|
319
|
+
m++
|
|
320
|
+
begin = end
|
|
321
|
+
} else {
|
|
322
|
+
begin = daysBefore[m]
|
|
323
|
+
}
|
|
324
|
+
return year, Month(m + 1), day - begin + 1, yday
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// absWeekday returns the weekday of the day abs falls in.
|
|
328
|
+
func absWeekday(abs int64) Weekday {
|
|
329
|
+
// January 1 of the year 1 was a Monday.
|
|
330
|
+
d := floorDiv(abs, secondsPerDay) + 1
|
|
331
|
+
return Weekday(d - 7*floorDiv(d, 7))
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Date returns the year, month, and day in which t occurs.
|
|
335
|
+
func (t Time) Date() (year int, month Month, day int) {
|
|
336
|
+
year, month, day, _ = absDate(t.abs())
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Year returns the year in which t occurs.
|
|
341
|
+
func (t Time) Year() int {
|
|
342
|
+
year, _, _, _ := absDate(t.abs())
|
|
343
|
+
return year
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Month returns the month of the year specified by t.
|
|
347
|
+
func (t Time) Month() Month {
|
|
348
|
+
_, month, _, _ := absDate(t.abs())
|
|
349
|
+
return month
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Day returns the day of the month specified by t.
|
|
353
|
+
func (t Time) Day() int {
|
|
354
|
+
_, _, day, _ := absDate(t.abs())
|
|
355
|
+
return day
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Weekday returns the day of the week specified by t.
|
|
359
|
+
func (t Time) Weekday() Weekday {
|
|
360
|
+
return absWeekday(t.abs())
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// ISOWeek returns the ISO 8601 year and week number in which t occurs. Week
|
|
364
|
+
// ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to week 52 or
|
|
365
|
+
// 53 of year n-1, and Dec 29 to Dec 31 might belong to week 1 of year n+1.
|
|
366
|
+
func (t Time) ISOWeek() (year, week int) {
|
|
367
|
+
// The first calendar week of a year is the week including its first
|
|
368
|
+
// Thursday; weeks start on Monday, so move to the Thursday of this week.
|
|
369
|
+
abs := t.abs()
|
|
370
|
+
d := Thursday - absWeekday(abs)
|
|
371
|
+
// handle Sunday
|
|
372
|
+
if d == 4 {
|
|
373
|
+
d = -3
|
|
374
|
+
}
|
|
375
|
+
abs += int64(d) * secondsPerDay
|
|
376
|
+
year, _, _, yday := absDate(abs)
|
|
377
|
+
return year, yday/7 + 1
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Clock returns the hour, minute, and second within the day specified by t.
|
|
381
|
+
func (t Time) Clock() (hour, min, sec int) {
|
|
382
|
+
abs := t.abs()
|
|
383
|
+
s := int(abs - floorDiv(abs, secondsPerDay)*secondsPerDay)
|
|
384
|
+
hour = s / secondsPerHour
|
|
385
|
+
s -= hour * secondsPerHour
|
|
386
|
+
min = s / secondsPerMinute
|
|
387
|
+
sec = s - min*secondsPerMinute
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Hour returns the hour within the day specified by t, in the range [0, 23].
|
|
392
|
+
func (t Time) Hour() int {
|
|
393
|
+
h, _, _ := t.Clock()
|
|
394
|
+
return h
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Minute returns the minute offset within the hour specified by t, in the
|
|
398
|
+
// range [0, 59].
|
|
399
|
+
func (t Time) Minute() int {
|
|
400
|
+
_, m, _ := t.Clock()
|
|
401
|
+
return m
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Second returns the second offset within the minute specified by t, in the
|
|
405
|
+
// range [0, 59].
|
|
406
|
+
func (t Time) Second() int {
|
|
407
|
+
_, _, s := t.Clock()
|
|
408
|
+
return s
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Nanosecond returns the nanosecond offset within the second specified by t,
|
|
412
|
+
// in the range [0, 999999999].
|
|
413
|
+
func (t Time) Nanosecond() int { return int(t.nsec) }
|
|
414
|
+
|
|
415
|
+
// YearDay returns the day of the year specified by t, in the range [1,365]
|
|
416
|
+
// for non-leap years, and [1,366] in leap years.
|
|
417
|
+
func (t Time) YearDay() int {
|
|
418
|
+
_, _, _, yday := absDate(t.abs())
|
|
419
|
+
return yday + 1
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// After reports whether the time instant t is after u.
|
|
423
|
+
func (t Time) After(u Time) bool {
|
|
424
|
+
return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Before reports whether the time instant t is before u.
|
|
428
|
+
func (t Time) Before(u Time) bool {
|
|
429
|
+
return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Compare compares the time instant t with u. If t is before u, it returns
|
|
433
|
+
// -1; if t is after u, it returns +1; if they're the same, it returns 0.
|
|
434
|
+
func (t Time) Compare(u Time) int {
|
|
435
|
+
switch {
|
|
436
|
+
case t.Before(u):
|
|
437
|
+
return -1
|
|
438
|
+
case t.After(u):
|
|
439
|
+
return +1
|
|
440
|
+
}
|
|
441
|
+
return 0
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Equal reports whether t and u represent the same time instant. Two times
|
|
445
|
+
// can be equal even if they are in different locations.
|
|
446
|
+
func (t Time) Equal(u Time) bool {
|
|
447
|
+
return t.sec == u.sec && t.nsec == u.nsec
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// IsZero reports whether t represents the zero time instant, January 1, year
|
|
451
|
+
// 1, 00:00:00 UTC.
|
|
452
|
+
func (t Time) IsZero() bool {
|
|
453
|
+
return t.sec == 0 && t.nsec == 0
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Add returns the time t+d.
|
|
457
|
+
func (t Time) Add(d Duration) Time {
|
|
458
|
+
dsec := int64(d / 1000000000)
|
|
459
|
+
nsec := t.nsec + int32(d%1000000000)
|
|
460
|
+
if nsec >= 1000000000 {
|
|
461
|
+
dsec++
|
|
462
|
+
nsec -= 1000000000
|
|
463
|
+
} else if nsec < 0 {
|
|
464
|
+
dsec--
|
|
465
|
+
nsec += 1000000000
|
|
466
|
+
}
|
|
467
|
+
t.sec += dsec
|
|
468
|
+
t.nsec = nsec
|
|
469
|
+
return t
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Sub returns the duration t-u. If the result exceeds the maximum (or
|
|
473
|
+
// minimum) value that can be stored in a Duration, the maximum (or minimum)
|
|
474
|
+
// duration will be returned.
|
|
475
|
+
func (t Time) Sub(u Time) Duration {
|
|
476
|
+
d := Duration(t.sec-u.sec)*Second + Duration(t.nsec-u.nsec)
|
|
477
|
+
// Check for overflow or underflow.
|
|
478
|
+
switch {
|
|
479
|
+
case u.Add(d).Equal(t):
|
|
480
|
+
return d // d is correct
|
|
481
|
+
case t.Before(u):
|
|
482
|
+
return minDuration // t - u is negative out of range
|
|
483
|
+
default:
|
|
484
|
+
return maxDuration // t - u is positive out of range
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Since returns the time elapsed since t.
|
|
489
|
+
func Since(t Time) Duration {
|
|
490
|
+
return Now().Sub(t)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Until returns the duration until t.
|
|
494
|
+
func Until(t Time) Duration {
|
|
495
|
+
return t.Sub(Now())
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// norm returns nhi, nlo such that
|
|
499
|
+
//
|
|
500
|
+
// hi * base + lo == nhi * base + nlo
|
|
501
|
+
// 0 <= nlo < base
|
|
502
|
+
func norm(hi, lo, base int) (nhi, nlo int) {
|
|
503
|
+
if lo < 0 {
|
|
504
|
+
n := (-lo-1)/base + 1
|
|
505
|
+
hi -= n
|
|
506
|
+
lo += n * base
|
|
507
|
+
}
|
|
508
|
+
if lo >= base {
|
|
509
|
+
n := lo / base
|
|
510
|
+
hi += n
|
|
511
|
+
lo -= n * base
|
|
512
|
+
}
|
|
513
|
+
return hi, lo
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Date returns the Time corresponding to
|
|
517
|
+
//
|
|
518
|
+
// yyyy-mm-dd hh:mm:ss + nsec nanoseconds
|
|
519
|
+
//
|
|
520
|
+
// in the appropriate zone for that time in the given location.
|
|
521
|
+
//
|
|
522
|
+
// The month, day, hour, min, sec, and nsec values may be outside their usual
|
|
523
|
+
// ranges and will be normalized during the conversion. For example, October
|
|
524
|
+
// 32 converts to November 1.
|
|
525
|
+
//
|
|
526
|
+
// Date panics if loc is nil.
|
|
527
|
+
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {
|
|
528
|
+
if loc == nil {
|
|
529
|
+
panic("time: missing Location in call to Date")
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Normalize month, overflowing into year.
|
|
533
|
+
m := int(month) - 1
|
|
534
|
+
year, m = norm(year, m, 12)
|
|
535
|
+
month = Month(m) + 1
|
|
536
|
+
|
|
537
|
+
// Normalize nsec, sec, min, hour, overflowing into day.
|
|
538
|
+
sec, nsec = norm(sec, nsec, 1000000000)
|
|
539
|
+
min, sec = norm(min, sec, 60)
|
|
540
|
+
hour, min = norm(hour, min, 60)
|
|
541
|
+
day, hour = norm(day, hour, 24)
|
|
542
|
+
|
|
543
|
+
// Compute days since the epoch.
|
|
544
|
+
d := daysSinceEpoch(year)
|
|
545
|
+
d += int64(daysBefore[month-1])
|
|
546
|
+
if isLeap(year) && month >= March {
|
|
547
|
+
d++ // February 29
|
|
548
|
+
}
|
|
549
|
+
d += int64(day - 1)
|
|
550
|
+
abs := d * secondsPerDay
|
|
551
|
+
abs += int64(hour*secondsPerHour + min*secondsPerMinute + sec)
|
|
552
|
+
|
|
553
|
+
// The wall clock reading is abs in loc; find the offset that was in
|
|
554
|
+
// effect, first guessing with the reading itself as the UTC time.
|
|
555
|
+
unix := abs + internalToUnix
|
|
556
|
+
_, offset := lookupZone(loc, unix)
|
|
557
|
+
if offset != 0 {
|
|
558
|
+
_, offset = lookupZone(loc, unix-int64(offset))
|
|
559
|
+
}
|
|
560
|
+
t := Time{sec: abs - int64(offset), nsec: int32(nsec)}
|
|
561
|
+
return t.setLoc(loc)
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Unix returns the local Time corresponding to the given Unix time, sec
|
|
565
|
+
// seconds and nsec nanoseconds since January 1, 1970 UTC. It is valid to pass
|
|
566
|
+
// nsec outside the range [0, 999999999].
|
|
567
|
+
func Unix(sec int64, nsec int64) Time {
|
|
568
|
+
if nsec < 0 || nsec >= 1000000000 {
|
|
569
|
+
n := nsec / 1000000000
|
|
570
|
+
sec += n
|
|
571
|
+
nsec -= n * 1000000000
|
|
572
|
+
if nsec < 0 {
|
|
573
|
+
nsec += 1000000000
|
|
574
|
+
sec--
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return Time{sec: sec + unixToInternal, nsec: int32(nsec), loc: Local}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// UnixMilli returns the local Time corresponding to the given Unix time, msec
|
|
581
|
+
// milliseconds since January 1, 1970 UTC.
|
|
582
|
+
func UnixMilli(msec int64) Time {
|
|
583
|
+
return Unix(msec/1000, (msec%1000)*1000000)
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// UnixMicro returns the local Time corresponding to the given Unix time, usec
|
|
587
|
+
// microseconds since January 1, 1970 UTC.
|
|
588
|
+
func UnixMicro(usec int64) Time {
|
|
589
|
+
return Unix(usec/1000000, (usec%1000000)*1000)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Now returns the current local time.
|
|
593
|
+
func Now() Time {
|
|
594
|
+
n := hostNow()
|
|
595
|
+
return Time{sec: n/1000000000 + unixToInternal, nsec: int32(n % 1000000000), loc: Local}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Unix returns t as a Unix time, the number of seconds elapsed since January
|
|
599
|
+
// 1, 1970 UTC.
|
|
600
|
+
func (t Time) Unix() int64 { return t.unixSec() }
|
|
601
|
+
|
|
602
|
+
// UnixMilli returns t as a Unix time, the number of milliseconds elapsed since
|
|
603
|
+
// January 1, 1970 UTC.
|
|
604
|
+
func (t Time) UnixMilli() int64 {
|
|
605
|
+
return t.unixSec()*1000 + int64(t.nsec)/1000000
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// UnixMicro returns t as a Unix time, the number of microseconds elapsed since
|
|
609
|
+
// January 1, 1970 UTC.
|
|
610
|
+
func (t Time) UnixMicro() int64 {
|
|
611
|
+
return t.unixSec()*1000000 + int64(t.nsec)/1000
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// UnixNano returns t as a Unix time, the number of nanoseconds elapsed since
|
|
615
|
+
// January 1, 1970 UTC. The result is undefined if the Unix time in
|
|
616
|
+
// nanoseconds cannot be represented by an int64 (a date before the year 1678
|
|
617
|
+
// or after 2262).
|
|
618
|
+
func (t Time) UnixNano() int64 {
|
|
619
|
+
return t.unixSec()*1000000000 + int64(t.nsec)
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// UTC returns t with the location set to UTC.
|
|
623
|
+
func (t Time) UTC() Time { return t.setLoc(UTC) }
|
|
624
|
+
|
|
625
|
+
// Local returns t with the location set to local time.
|
|
626
|
+
func (t Time) Local() Time { return t.setLoc(Local) }
|
|
627
|
+
|
|
628
|
+
// In returns a copy of t representing the same time instant, but with the
|
|
629
|
+
// copy's location information set to loc for display purposes.
|
|
630
|
+
//
|
|
631
|
+
// In panics if loc is nil.
|
|
632
|
+
func (t Time) In(loc *Location) Time {
|
|
633
|
+
if loc == nil {
|
|
634
|
+
panic("time: missing Location in call to Time.In")
|
|
635
|
+
}
|
|
636
|
+
return t.setLoc(loc)
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Location returns the time zone information associated with t.
|
|
640
|
+
func (t Time) Location() *Location {
|
|
641
|
+
l := t.loc
|
|
642
|
+
if l == nil {
|
|
643
|
+
l = UTC
|
|
644
|
+
}
|
|
645
|
+
return l
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Zone computes the time zone in effect at time t, returning the abbreviated
|
|
649
|
+
// name of the zone (such as "CET") and its offset in seconds east of UTC.
|
|
650
|
+
func (t Time) Zone() (name string, offset int) {
|
|
651
|
+
return t.zone()
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// AddDate returns the time corresponding to adding the given number of years,
|
|
655
|
+
// months, and days to t. For example, AddDate(-1, 2, 3) applied to January 1,
|
|
656
|
+
// 2011 returns March 4, 2010.
|
|
657
|
+
//
|
|
658
|
+
// AddDate normalizes its result in the same way that Date does, so, for
|
|
659
|
+
// example, adding one month to October 31 yields December 1, the normalized
|
|
660
|
+
// form for November 31.
|
|
661
|
+
func (t Time) AddDate(years int, months int, days int) Time {
|
|
662
|
+
year, month, day := t.Date()
|
|
663
|
+
hour, min, sec := t.Clock()
|
|
664
|
+
return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.Location())
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// div divides t by d and returns the remainder, and whether the quotient is
|
|
668
|
+
// odd. The quotient is not needed beyond its parity.
|
|
669
|
+
func div(t Time, d Duration) (qmod2 int, r Duration) {
|
|
670
|
+
neg := false
|
|
671
|
+
nsec := t.nsec
|
|
672
|
+
sec := t.sec
|
|
673
|
+
if sec < 0 {
|
|
674
|
+
// Operate on absolute value.
|
|
675
|
+
neg = true
|
|
676
|
+
sec = -sec
|
|
677
|
+
nsec = -nsec
|
|
678
|
+
if nsec < 0 {
|
|
679
|
+
nsec += 1000000000
|
|
680
|
+
sec-- // sec >= 1 before the -- so safe
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
switch {
|
|
685
|
+
// Special case: 2d divides 1 second.
|
|
686
|
+
case d < Second && Second%(d+d) == 0:
|
|
687
|
+
qmod2 = int(nsec/int32(d)) & 1
|
|
688
|
+
r = Duration(nsec % int32(d))
|
|
689
|
+
|
|
690
|
+
// Special case: d is a multiple of 1 second.
|
|
691
|
+
case d%Second == 0:
|
|
692
|
+
d1 := int64(d / Second)
|
|
693
|
+
qmod2 = int(sec/d1) & 1
|
|
694
|
+
r = Duration(sec%d1)*Second + Duration(nsec)
|
|
695
|
+
|
|
696
|
+
// General case.
|
|
697
|
+
// This could be faster if more cleverness were applied,
|
|
698
|
+
// but it's really only here to avoid special case restrictions in the API.
|
|
699
|
+
// No one will care about these cases.
|
|
700
|
+
default:
|
|
701
|
+
// Compute nanoseconds as 128-bit number.
|
|
702
|
+
usec := uint64(sec)
|
|
703
|
+
tmp := (usec >> 32) * 1000000000
|
|
704
|
+
u1 := tmp >> 32
|
|
705
|
+
u0 := tmp << 32
|
|
706
|
+
tmp = (usec & 0xFFFFFFFF) * 1000000000
|
|
707
|
+
u0x := u0
|
|
708
|
+
u0 = u0 + tmp
|
|
709
|
+
if u0 < u0x {
|
|
710
|
+
u1++
|
|
711
|
+
}
|
|
712
|
+
u0x = u0
|
|
713
|
+
u0 = u0 + uint64(nsec)
|
|
714
|
+
if u0 < u0x {
|
|
715
|
+
u1++
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Compute remainder by subtracting r<<k for decreasing k.
|
|
719
|
+
// Quotient parity is whether we subtract on last round.
|
|
720
|
+
d1 := uint64(d)
|
|
721
|
+
for d1>>63 != 1 {
|
|
722
|
+
d1 <<= 1
|
|
723
|
+
}
|
|
724
|
+
d0 := uint64(0)
|
|
725
|
+
for {
|
|
726
|
+
qmod2 = 0
|
|
727
|
+
if u1 > d1 || u1 == d1 && u0 >= d0 {
|
|
728
|
+
// subtract
|
|
729
|
+
qmod2 = 1
|
|
730
|
+
u0x = u0
|
|
731
|
+
u0 = u0 - d0
|
|
732
|
+
if u0 > u0x {
|
|
733
|
+
u1--
|
|
734
|
+
}
|
|
735
|
+
u1 -= d1
|
|
736
|
+
}
|
|
737
|
+
if d1 == 0 && d0 == uint64(d) {
|
|
738
|
+
break
|
|
739
|
+
}
|
|
740
|
+
d0 >>= 1
|
|
741
|
+
d0 |= (d1 & 1) << 63
|
|
742
|
+
d1 >>= 1
|
|
743
|
+
}
|
|
744
|
+
r = Duration(u0)
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
if neg && r != 0 {
|
|
748
|
+
// If input was negative and not an exact multiple of d, we computed q, r such that
|
|
749
|
+
// q*d + r = -t
|
|
750
|
+
// But the right answers are given by -(q-1), d-r:
|
|
751
|
+
// q*d + r = -t
|
|
752
|
+
// -q*d - r = t
|
|
753
|
+
// -(q-1)*d + (d - r) = t
|
|
754
|
+
qmod2 ^= 1
|
|
755
|
+
r = d - r
|
|
756
|
+
}
|
|
757
|
+
return
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// Truncate returns the result of rounding t down to a multiple of d (since
|
|
761
|
+
// the zero time). If d <= 0, Truncate returns t unchanged.
|
|
762
|
+
func (t Time) Truncate(d Duration) Time {
|
|
763
|
+
if d <= 0 {
|
|
764
|
+
return t
|
|
765
|
+
}
|
|
766
|
+
_, r := div(t, d)
|
|
767
|
+
return t.Add(-r)
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Round returns the result of rounding t to the nearest multiple of d (since
|
|
771
|
+
// the zero time). The rounding behavior for halfway values is to round up. If
|
|
772
|
+
// d <= 0, Round returns t unchanged.
|
|
773
|
+
func (t Time) Round(d Duration) Time {
|
|
774
|
+
if d <= 0 {
|
|
775
|
+
return t
|
|
776
|
+
}
|
|
777
|
+
_, r := div(t, d)
|
|
778
|
+
if lessThanHalf(r, d) {
|
|
779
|
+
return t.Add(-r)
|
|
780
|
+
}
|
|
781
|
+
return t.Add(d - r)
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// ParseError describes a problem parsing a time string.
|
|
785
|
+
type ParseError struct {
|
|
786
|
+
Layout string
|
|
787
|
+
Value string
|
|
788
|
+
LayoutElem string
|
|
789
|
+
ValueElem string
|
|
790
|
+
Message string
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Error returns the string representation of a ParseError.
|
|
794
|
+
func (e *ParseError) Error() string {
|
|
795
|
+
if e.Message == "" {
|
|
796
|
+
return "parsing time " +
|
|
797
|
+
quote(e.Value) + " as " +
|
|
798
|
+
quote(e.Layout) + ": cannot parse " +
|
|
799
|
+
quote(e.ValueElem) + " as " +
|
|
800
|
+
quote(e.LayoutElem)
|
|
801
|
+
}
|
|
802
|
+
return "parsing time " +
|
|
803
|
+
quote(e.Value) + e.Message
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// quote returns s as a double-quoted string, escaping what Go's strconv.Quote
|
|
807
|
+
// escapes for the characters a layout or value can hold.
|
|
808
|
+
func quote(s string) string {
|
|
809
|
+
const lowerhex = "0123456789abcdef"
|
|
810
|
+
buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes
|
|
811
|
+
buf[0] = '"'
|
|
812
|
+
for i := 0; i < len(s); i++ {
|
|
813
|
+
c := byte(s[i])
|
|
814
|
+
switch {
|
|
815
|
+
case c >= 0x80:
|
|
816
|
+
// Pass multi-byte characters through unchanged.
|
|
817
|
+
buf = append(buf, c)
|
|
818
|
+
case c == '"' || c == '\\':
|
|
819
|
+
buf = append(buf, '\\', c)
|
|
820
|
+
case c == '\n':
|
|
821
|
+
buf = append(buf, '\\', 'n')
|
|
822
|
+
case c == '\r':
|
|
823
|
+
buf = append(buf, '\\', 'r')
|
|
824
|
+
case c == '\t':
|
|
825
|
+
buf = append(buf, '\\', 't')
|
|
826
|
+
case c < ' ' || c == 0x7f:
|
|
827
|
+
buf = append(buf, '\\', 'x', lowerhex[c>>4], lowerhex[c&0xF])
|
|
828
|
+
default:
|
|
829
|
+
buf = append(buf, c)
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
buf = append(buf, '"')
|
|
833
|
+
return string(buf)
|
|
834
|
+
}
|