Skip to content

Commit 32a8a96

Browse files
authored
Merge pull request #1280 from Workiva/tempTimeFix
[go1.20] Added temporary generics override for time formatting
2 parents 713ce26 + 0df0881 commit 32a8a96

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

compiler/natives/src/time/format.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//go:build js
2+
// +build js
3+
4+
package time
5+
6+
// copied and replaced for go1.20 temporarily without generics.
7+
func atoi(sAny any) (x int, err error) {
8+
s := asBytes(sAny)
9+
neg := false
10+
if len(s) > 0 && (s[0] == '-' || s[0] == '+') {
11+
neg = s[0] == '-'
12+
s = s[1:]
13+
}
14+
q, remStr, err := leadingInt(s)
15+
rem := []byte(remStr)
16+
x = int(q)
17+
if err != nil || len(rem) > 0 {
18+
return 0, atoiError
19+
}
20+
if neg {
21+
x = -x
22+
}
23+
return x, nil
24+
}
25+
26+
// copied and replaced for go1.20 temporarily without generics.
27+
func isDigit(sAny any, i int) bool {
28+
s := asBytes(sAny)
29+
if len(s) <= i {
30+
return false
31+
}
32+
c := s[i]
33+
return '0' <= c && c <= '9'
34+
}
35+
36+
// copied and replaced for go1.20 temporarily without generics.
37+
func parseNanoseconds(sAny any, nbytes int) (ns int, rangeErrString string, err error) {
38+
value := asBytes(sAny)
39+
if !commaOrPeriod(value[0]) {
40+
err = errBad
41+
return
42+
}
43+
if nbytes > 10 {
44+
value = value[:10]
45+
nbytes = 10
46+
}
47+
if ns, err = atoi(value[1:nbytes]); err != nil {
48+
return
49+
}
50+
if ns < 0 {
51+
rangeErrString = "fractional second"
52+
return
53+
}
54+
scaleDigits := 10 - nbytes
55+
for i := 0; i < scaleDigits; i++ {
56+
ns *= 10
57+
}
58+
return
59+
}
60+
61+
// copied and replaced for go1.20 temporarily without generics.
62+
func leadingInt(sAny any) (x uint64, rem string, err error) {
63+
s := asBytes(sAny)
64+
i := 0
65+
for ; i < len(s); i++ {
66+
c := s[i]
67+
if c < '0' || c > '9' {
68+
break
69+
}
70+
if x > 1<<63/10 {
71+
return 0, rem, errLeadingInt
72+
}
73+
x = x*10 + uint64(c) - '0'
74+
if x > 1<<63 {
75+
return 0, rem, errLeadingInt
76+
}
77+
}
78+
return x, string(s[i:]), nil
79+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//go:build js
2+
// +build js
3+
4+
package time
5+
6+
import "errors"
7+
8+
// added for go1.20 temporarily without generics.
9+
func asBytes(s any) []byte {
10+
switch t := s.(type) {
11+
case []byte:
12+
return t
13+
case string:
14+
return []byte(t)
15+
default:
16+
panic(errors.New(`unexpected type passed to asBytes, expected string or []bytes`))
17+
}
18+
}
19+
20+
// copied and replaced for go1.20 temporarily without generics.
21+
func parseRFC3339(sAny any, local *Location) (Time, bool) {
22+
s := asBytes(sAny)
23+
ok := true
24+
parseUint := func(s []byte, min, max int) (x int) {
25+
for _, c := range s {
26+
if c < '0' || '9' < c {
27+
ok = false
28+
return min
29+
}
30+
x = x*10 + int(c) - '0'
31+
}
32+
if x < min || max < x {
33+
ok = false
34+
return min
35+
}
36+
return x
37+
}
38+
39+
if len(s) < len("2006-01-02T15:04:05") {
40+
return Time{}, false
41+
}
42+
year := parseUint(s[0:4], 0, 9999)
43+
month := parseUint(s[5:7], 1, 12)
44+
day := parseUint(s[8:10], 1, daysIn(Month(month), year))
45+
hour := parseUint(s[11:13], 0, 23)
46+
min := parseUint(s[14:16], 0, 59)
47+
sec := parseUint(s[17:19], 0, 59)
48+
if !ok || !(s[4] == '-' && s[7] == '-' && s[10] == 'T' && s[13] == ':' && s[16] == ':') {
49+
return Time{}, false
50+
}
51+
s = s[19:]
52+
53+
var nsec int
54+
if len(s) >= 2 && s[0] == '.' && isDigit(s, 1) {
55+
n := 2
56+
for ; n < len(s) && isDigit(s, n); n++ {
57+
}
58+
nsec, _, _ = parseNanoseconds(s, n)
59+
s = s[n:]
60+
}
61+
62+
t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
63+
if len(s) != 1 || s[0] != 'Z' {
64+
if len(s) != len("-07:00") {
65+
return Time{}, false
66+
}
67+
hr := parseUint(s[1:3], 0, 23)
68+
mm := parseUint(s[4:6], 0, 59)
69+
if !ok || !((s[0] == '-' || s[0] == '+') && s[3] == ':') {
70+
return Time{}, false
71+
}
72+
zoneOffset := (hr*60 + mm) * 60
73+
if s[0] == '-' {
74+
zoneOffset *= -1
75+
}
76+
t.addSec(-int64(zoneOffset))
77+
78+
if _, offset, _, _, _ := local.lookup(t.unixSec()); offset == zoneOffset {
79+
t.setLoc(local)
80+
} else {
81+
t.setLoc(FixedZone("", zoneOffset))
82+
}
83+
}
84+
return t, true
85+
}

0 commit comments

Comments
 (0)