aboutsummaryrefslogtreecommitdiff
path: root/src/time/format.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/time/format.go')
-rw-r--r--src/time/format.go52
1 files changed, 40 insertions, 12 deletions
diff --git a/src/time/format.go b/src/time/format.go
index 7ae89c557d..7373892b97 100644
--- a/src/time/format.go
+++ b/src/time/format.go
@@ -74,7 +74,7 @@ import "errors"
// for compatibility with fixed-width Unix time formats. A leading zero represents
// a zero-padded value.
//
-// The formats and 002 are space-padded and zero-padded
+// The formats __2 and 002 are space-padded and zero-padded
// three-character day of year; there is no unpadded day of year format.
//
// A comma or decimal point followed by one or more zeros represents
@@ -146,10 +146,11 @@ const (
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
- stdNeedDate = 1 << 8 // need month, day, year
- stdNeedClock = 2 << 8 // need hour, minute, second
- stdArgShift = 16 // extra argument in high bits, above low stdArgShift
- stdMask = 1<<stdArgShift - 1 // mask out argument
+ stdNeedDate = 1 << 8 // need month, day, year
+ stdNeedClock = 2 << 8 // need hour, minute, second
+ stdArgShift = 16 // extra argument in high bits, above low stdArgShift
+ stdSeparatorShift = 28 // extra argument in high 4 bits for fractional second separators
+ stdMask = 1<<stdArgShift - 1 // mask out argument
)
// std0x records the std values for "01", "02", ..., "06".
@@ -289,11 +290,11 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
}
// String of digits must end here - only fractional second is all digits.
if !isDigit(layout, j) {
- std := stdFracSecond0
+ code := stdFracSecond0
if layout[i+1] == '9' {
- std = stdFracSecond9
+ code = stdFracSecond9
}
- std |= (j - (i + 1)) << stdArgShift
+ std := stdFracSecond(code, j-(i+1), c)
return layout[0:i], std, layout[j:]
}
}
@@ -430,9 +431,36 @@ func atoi(s string) (x int, err error) {
return x, nil
}
+// The "std" value passed to formatNano contains two packed fields: the number of
+// digits after the decimal and the separator character (period or comma).
+// These functions pack and unpack that variable.
+func stdFracSecond(code, n, c int) int {
+ // Use 0xfff to make the failure case even more absurd.
+ if c == '.' {
+ return code | ((n & 0xfff) << stdArgShift)
+ }
+ return code | ((n & 0xfff) << stdArgShift) | 1<<stdSeparatorShift
+}
+
+func digitsLen(std int) int {
+ return (std >> stdArgShift) & 0xfff
+}
+
+func separator(std int) byte {
+ if (std >> stdSeparatorShift) == 0 {
+ return '.'
+ }
+ return ','
+}
+
// formatNano appends a fractional second, as nanoseconds, to b
// and returns the result.
-func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
+func formatNano(b []byte, nanosec uint, std int) []byte {
+ var (
+ n = digitsLen(std)
+ separator = separator(std)
+ trim = std&stdMask == stdFracSecond9
+ )
u := nanosec
var buf [9]byte
for start := len(buf); start > 0; {
@@ -452,7 +480,7 @@ func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
return b
}
}
- b = append(b, '.')
+ b = append(b, separator)
return append(b, buf[:n]...)
}
@@ -733,7 +761,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
b = appendInt(b, zone/60, 2)
b = appendInt(b, zone%60, 2)
case stdFracSecond0, stdFracSecond9:
- b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
+ b = formatNano(b, uint(t.Nanosecond()), std)
}
}
return b
@@ -1165,7 +1193,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
case stdFracSecond0:
// stdFracSecond0 requires the exact number of digits as specified in
// the layout.
- ndigit := 1 + (std >> stdArgShift)
+ ndigit := 1 + digitsLen(std)
if len(value) < ndigit {
err = errBad
break