@@ -35,6 +35,11 @@ import (
35
35
// %M: The minute as a decimal number, padded to 2 digits with a leading 0, in the range 00 to 59.
36
36
// %S: The second as a decimal number, padded to 2 digits with a leading 0, in the range 00 to 59.
37
37
//
38
+ // %f: Equivalent to %6f.
39
+ // %3f: The millisecond offset within the represented second, rounded either up or down and padded to 3 digits with a leading 0.
40
+ // %6f: The microsecond offset within the represented second, rounded either up or down and padded to 6 digits with a leading 0.
41
+ // %9f: The nanosecond offset within the represented second, padded to 9 digits with a leading 0.
42
+ //
38
43
// When formatting using specifiers that represent padded decimals, leading 0s can be omitted using the '-' character after the '%'.
39
44
// For example, '%m' may produce the string '04' (for March), but '%-m' produces '4'.
40
45
// However, when parsing using these specifiers, it is not required that the input string contains any leading zeros.
@@ -110,11 +115,11 @@ NextChar:
110
115
buf = append (buf , c )
111
116
112
117
if len (buf ) >= 2 && buf [0 ] == '%' {
113
- if c == '-' || c == 'E' {
118
+ if c == '-' || c == 'E' || ( c >= '0' && c <= '9' ) {
114
119
continue NextChar
115
120
}
116
121
117
- nopad , localed , main , err := parseSpecifier (buf )
122
+ nopad , localed , precision , main , err := parseSpecifier (buf )
118
123
if err != nil {
119
124
return "" , err
120
125
}
@@ -147,6 +152,22 @@ NextChar:
147
152
}
148
153
case date != nil && main == 'd' : // %d
149
154
out = append (out , []rune (decimal (day , 2 ))... )
155
+ case time != nil && main == 'f' : // %f
156
+ if precision == 0 {
157
+ precision = 6
158
+ }
159
+
160
+ nanos := time .Nanosecond ()
161
+ switch precision {
162
+ case 3 : // %3f
163
+ out = append (out , []rune (decimal (divideAndRoundInt (nanos , 1000000 ), 3 ))... )
164
+ case 6 : // %6f
165
+ out = append (out , []rune (decimal (divideAndRoundInt (nanos , 1000 ), 6 ))... )
166
+ case 9 : // %9f
167
+ out = append (out , []rune (decimal (nanos , 9 ))... )
168
+ default :
169
+ panic (fmt .Sprintf ("unsupported specifier '%df'" , precision ))
170
+ }
150
171
case date != nil && main == 'G' : // %G
151
172
y , _ := date .ISOWeek ()
152
173
out = append (out , []rune (decimal (y , 4 ))... )
@@ -347,7 +368,7 @@ func parse(layout, value string, date, time *int64) error {
347
368
return string (_lower [:i ]), string (_original [:i ])
348
369
}
349
370
350
- _ , localed , main , err := parseSpecifier (buf )
371
+ _ , localed , precision , main , err := parseSpecifier (buf )
351
372
if err != nil {
352
373
return err
353
374
}
@@ -398,6 +419,30 @@ func parse(layout, value string, date, time *int64) error {
398
419
if day , err = integer (2 ); err != nil {
399
420
return err
400
421
}
422
+ case time != nil && main == 'f' : // %f
423
+ if precision == 0 {
424
+ precision = 6
425
+ }
426
+
427
+ switch precision {
428
+ case 3 : // %3f
429
+ millis , err := integer (3 )
430
+ if err != nil {
431
+ return err
432
+ }
433
+ nsec = millis * 1000000
434
+ case 6 : // %6f
435
+ micros , err := integer (6 )
436
+ if err != nil {
437
+ return err
438
+ }
439
+ nsec = micros * 1000
440
+ case 9 : // %9f
441
+ if nsec , err = integer (9 ); err != nil {
442
+ return err
443
+ }
444
+ default :
445
+ }
401
446
case date != nil && main == 'G' : // %G
402
447
haveISODate = true
403
448
if isoYear , err = integer (4 ); err != nil {
@@ -488,7 +533,7 @@ func parse(layout, value string, date, time *int64) error {
488
533
var (
489
534
valid = i < len (layout )
490
535
isSpecifier = len (buf ) >= 2 && buf [0 ] == '%'
491
- specifierComplete = isSpecifier && (buf [len (buf )- 1 ] != '-' && buf [len (buf )- 1 ] != 'E' )
536
+ specifierComplete = isSpecifier && (buf [len (buf )- 1 ] != '-' && buf [len (buf )- 1 ] != 'E' && ( buf [ len ( buf ) - 1 ] < '0' || buf [ len ( buf ) - 1 ] > '9' ) )
492
537
isText = len (buf ) >= 1 && buf [0 ] != '%'
493
538
)
494
539
@@ -612,32 +657,34 @@ func parse(layout, value string, date, time *int64) error {
612
657
return nil
613
658
}
614
659
615
- func parseSpecifier (buf []rune ) (nopad , localed bool , main rune , err error ) {
660
+ func parseSpecifier (buf []rune ) (nopad , localed bool , precision uint , main rune , err error ) {
616
661
if len (buf ) == 3 {
617
- switch buf [ 1 ] {
618
- case '-' :
662
+ switch {
663
+ case buf [ 1 ] == '-' :
619
664
nopad = true
620
- case 'E' :
665
+ case buf [ 1 ] == 'E' :
621
666
localed = true
667
+ case buf [1 ] >= '0' && buf [1 ] <= '9' :
668
+ precision = uint (buf [1 ] - 48 )
622
669
default :
623
- return false , false , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
670
+ return false , false , 0 , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
624
671
}
625
672
} else if len (buf ) == 4 {
626
673
switch buf [1 ] {
627
674
case '-' :
628
675
nopad = true
629
676
default :
630
- return false , false , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
677
+ return false , false , 0 , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
631
678
}
632
679
633
680
switch buf [2 ] {
634
681
case 'E' :
635
682
localed = true
636
683
default :
637
- return false , false , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
684
+ return false , false , 0 , 0 , fmt .Errorf ("unsupported modifier '%c'" , buf [1 ])
638
685
}
639
686
}
640
- return nopad , localed , buf [len (buf )- 1 ], nil
687
+ return nopad , localed , precision , buf [len (buf )- 1 ], nil
641
688
}
642
689
643
690
func convert12To24HourClock (hour12 int , isAfternoon bool ) (hour24 int ) {
0 commit comments