@@ -146,10 +146,11 @@ const (
146
146
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
147
147
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
148
148
149
- stdNeedDate = 1 << 8 // need month, day, year
150
- stdNeedClock = 2 << 8 // need hour, minute, second
151
- stdArgShift = 16 // extra argument in high bits, above low stdArgShift
152
- stdMask = 1 << stdArgShift - 1 // mask out argument
149
+ stdNeedDate = 1 << 8 // need month, day, year
150
+ stdNeedClock = 2 << 8 // need hour, minute, second
151
+ stdArgShift = 16 // extra argument in high bits, above low stdArgShift
152
+ stdSeparatorShift = 28 // extra argument in high 4 bits for fractional second separators
153
+ stdMask = 1 << stdArgShift - 1 // mask out argument
153
154
)
154
155
155
156
// std0x records the std values for "01", "02", ..., "06".
@@ -289,11 +290,11 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
289
290
}
290
291
// String of digits must end here - only fractional second is all digits.
291
292
if ! isDigit (layout , j ) {
292
- std := stdFracSecond0
293
+ code := stdFracSecond0
293
294
if layout [i + 1 ] == '9' {
294
- std = stdFracSecond9
295
+ code = stdFracSecond9
295
296
}
296
- std |= ( j - ( i + 1 )) << stdArgShift
297
+ std := stdFracSecond ( code , j - ( i + 1 ), c )
297
298
return layout [0 :i ], std , layout [j :]
298
299
}
299
300
}
@@ -430,9 +431,36 @@ func atoi(s string) (x int, err error) {
430
431
return x , nil
431
432
}
432
433
434
+ // The "std" value passed to formatNano contains two packed fields: the number of
435
+ // digits after the decimal and the separator character (period or comma).
436
+ // These functions pack and unpack that variable.
437
+ func stdFracSecond (code , n , c int ) int {
438
+ // Use 0xfff to make the failure case even more absurd.
439
+ if c == '.' {
440
+ return code | ((n & 0xfff ) << stdArgShift )
441
+ }
442
+ return code | ((n & 0xfff ) << stdArgShift ) | 1 << stdSeparatorShift
443
+ }
444
+
445
+ func digitsLen (std int ) int {
446
+ return (std >> stdArgShift ) & 0xfff
447
+ }
448
+
449
+ func separator (std int ) byte {
450
+ if (std >> stdSeparatorShift ) == 0 {
451
+ return '.'
452
+ }
453
+ return ','
454
+ }
455
+
433
456
// formatNano appends a fractional second, as nanoseconds, to b
434
457
// and returns the result.
435
- func formatNano (b []byte , nanosec uint , n int , trim bool ) []byte {
458
+ func formatNano (b []byte , nanosec uint , std int ) []byte {
459
+ var (
460
+ n = digitsLen (std )
461
+ separator = separator (std )
462
+ trim = std & stdMask == stdFracSecond9
463
+ )
436
464
u := nanosec
437
465
var buf [9 ]byte
438
466
for start := len (buf ); start > 0 ; {
@@ -452,7 +480,7 @@ func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
452
480
return b
453
481
}
454
482
}
455
- b = append (b , '.' )
483
+ b = append (b , separator )
456
484
return append (b , buf [:n ]... )
457
485
}
458
486
@@ -732,7 +760,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
732
760
b = appendInt (b , zone / 60 , 2 )
733
761
b = appendInt (b , zone % 60 , 2 )
734
762
case stdFracSecond0 , stdFracSecond9 :
735
- b = formatNano (b , uint (t .Nanosecond ()), std >> stdArgShift , std & stdMask == stdFracSecond9 )
763
+ b = formatNano (b , uint (t .Nanosecond ()), std )
736
764
}
737
765
}
738
766
return b
@@ -1164,7 +1192,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
1164
1192
case stdFracSecond0 :
1165
1193
// stdFracSecond0 requires the exact number of digits as specified in
1166
1194
// the layout.
1167
- ndigit := 1 + (std >> stdArgShift )
1195
+ ndigit := 1 + digitsLen (std )
1168
1196
if len (value ) < ndigit {
1169
1197
err = errBad
1170
1198
break
0 commit comments