Commit d5ef6981 authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Robert Griesemer

time: unify formatting of decimals for timestamps

Change function appendUint to appendInt with variable-width 0-padding.

This allows the decimal for the year to be generated without extra code
to handle the wider padding and directly handles negative numbers.

Removes the special casing for numbers with one and two digits.
The special case for 0 was unreachable.

The new version is slightly slower.

benchmark              old ns/op     new ns/op     delta
BenchmarkFormat        444           454           +2.25%
BenchmarkFormatNow     398           415           +4.27%

Change-Id: I4ddef96bf07ad35dca76053321d510441ec6d4f5
Reviewed-on: https://go-review.googlesource.com/2751Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 5c22a4a2
...@@ -315,36 +315,34 @@ func lookup(tab []string, val string) (int, string, error) { ...@@ -315,36 +315,34 @@ func lookup(tab []string, val string) (int, string, error) {
return -1, val, errBad return -1, val, errBad
} }
// appendUint appends the decimal form of x to b and returns the result. // appendInt appends the decimal form of x to b and returns the result.
// If x is a single-digit number and pad != 0, appendUint inserts the pad byte // If the decimal form (excluding sign) is shorter than width, the result is padded with leading 0's.
// before the digit.
// Duplicates functionality in strconv, but avoids dependency. // Duplicates functionality in strconv, but avoids dependency.
func appendUint(b []byte, x uint, pad byte) []byte { func appendInt(b []byte, x int, width int) []byte {
if x < 10 { u := uint(x)
if pad != 0 { if x < 0 {
b = append(b, pad) b = append(b, '-')
} u = uint(-x)
return append(b, byte('0'+x))
}
if x < 100 {
b = append(b, byte('0'+x/10))
b = append(b, byte('0'+x%10))
return b
} }
var buf [32]byte // Assemble decimal in reverse order.
n := len(buf) var buf [20]byte
if x == 0 { i := len(buf)
return append(b, '0') for u >= 10 {
i--
q := u / 10
buf[i] = byte('0' + u - q*10)
u = q
} }
for x >= 10 { i--
n-- buf[i] = byte('0' + u)
buf[n] = byte(x%10 + '0')
x /= 10 // Add 0-padding.
for w := len(buf) - i; w < width; w++ {
b = append(b, '0')
} }
n--
buf[n] = byte(x + '0') return append(b, buf[i:]...)
return append(b, buf[n:]...)
} }
// Never printed, just needs to be non-nil for return by atoi. // Never printed, just needs to be non-nil for return by atoi.
...@@ -458,75 +456,56 @@ func (t Time) Format(layout string) string { ...@@ -458,75 +456,56 @@ func (t Time) Format(layout string) string {
if y < 0 { if y < 0 {
y = -y y = -y
} }
b = appendUint(b, uint(y%100), '0') b = appendInt(b, y%100, 2)
case stdLongYear: case stdLongYear:
// Pad year to at least 4 digits. b = appendInt(b, year, 4)
y := year
switch {
case year <= -1000:
b = append(b, '-')
y = -y
case year <= -100:
b = append(b, "-0"...)
y = -y
case year <= -10:
b = append(b, "-00"...)
y = -y
case year < 0:
b = append(b, "-000"...)
y = -y
case year < 10:
b = append(b, "000"...)
case year < 100:
b = append(b, "00"...)
case year < 1000:
b = append(b, '0')
}
b = appendUint(b, uint(y), 0)
case stdMonth: case stdMonth:
b = append(b, month.String()[:3]...) b = append(b, month.String()[:3]...)
case stdLongMonth: case stdLongMonth:
m := month.String() m := month.String()
b = append(b, m...) b = append(b, m...)
case stdNumMonth: case stdNumMonth:
b = appendUint(b, uint(month), 0) b = appendInt(b, int(month), 0)
case stdZeroMonth: case stdZeroMonth:
b = appendUint(b, uint(month), '0') b = appendInt(b, int(month), 2)
case stdWeekDay: case stdWeekDay:
b = append(b, absWeekday(abs).String()[:3]...) b = append(b, absWeekday(abs).String()[:3]...)
case stdLongWeekDay: case stdLongWeekDay:
s := absWeekday(abs).String() s := absWeekday(abs).String()
b = append(b, s...) b = append(b, s...)
case stdDay: case stdDay:
b = appendUint(b, uint(day), 0) b = appendInt(b, day, 0)
case stdUnderDay: case stdUnderDay:
b = appendUint(b, uint(day), ' ') if day < 10 {
b = append(b, ' ')
}
b = appendInt(b, day, 0)
case stdZeroDay: case stdZeroDay:
b = appendUint(b, uint(day), '0') b = appendInt(b, day, 2)
case stdHour: case stdHour:
b = appendUint(b, uint(hour), '0') b = appendInt(b, hour, 2)
case stdHour12: case stdHour12:
// Noon is 12PM, midnight is 12AM. // Noon is 12PM, midnight is 12AM.
hr := hour % 12 hr := hour % 12
if hr == 0 { if hr == 0 {
hr = 12 hr = 12
} }
b = appendUint(b, uint(hr), 0) b = appendInt(b, hr, 0)
case stdZeroHour12: case stdZeroHour12:
// Noon is 12PM, midnight is 12AM. // Noon is 12PM, midnight is 12AM.
hr := hour % 12 hr := hour % 12
if hr == 0 { if hr == 0 {
hr = 12 hr = 12
} }
b = appendUint(b, uint(hr), '0') b = appendInt(b, hr, 2)
case stdMinute: case stdMinute:
b = appendUint(b, uint(min), 0) b = appendInt(b, min, 0)
case stdZeroMinute: case stdZeroMinute:
b = appendUint(b, uint(min), '0') b = appendInt(b, min, 2)
case stdSecond: case stdSecond:
b = appendUint(b, uint(sec), 0) b = appendInt(b, sec, 2)
case stdZeroSecond: case stdZeroSecond:
b = appendUint(b, uint(sec), '0') b = appendInt(b, sec, 2)
case stdPM: case stdPM:
if hour >= 12 { if hour >= 12 {
b = append(b, "PM"...) b = append(b, "PM"...)
...@@ -555,18 +534,18 @@ func (t Time) Format(layout string) string { ...@@ -555,18 +534,18 @@ func (t Time) Format(layout string) string {
} else { } else {
b = append(b, '+') b = append(b, '+')
} }
b = appendUint(b, uint(zone/60), '0') b = appendInt(b, zone/60, 2)
if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ { if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
b = append(b, ':') b = append(b, ':')
} }
b = appendUint(b, uint(zone%60), '0') b = appendInt(b, zone%60, 2)
// append seconds if appropriate // append seconds if appropriate
if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
b = append(b, ':') b = append(b, ':')
} }
b = appendUint(b, uint(absoffset%60), '0') b = appendInt(b, absoffset%60, 2)
} }
case stdTZ: case stdTZ:
...@@ -583,8 +562,8 @@ func (t Time) Format(layout string) string { ...@@ -583,8 +562,8 @@ func (t Time) Format(layout string) string {
} else { } else {
b = append(b, '+') b = append(b, '+')
} }
b = appendUint(b, uint(zone/60), '0') b = appendInt(b, zone/60, 2)
b = appendUint(b, uint(zone%60), '0') b = appendInt(b, zone%60, 2)
case stdFracSecond0, stdFracSecond9: case stdFracSecond0, stdFracSecond9:
b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9) b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment