diff options
author | Emmanuel T Odeke <emmanuel@orijtech.com> | 2021-03-11 17:34:09 -0800 |
---|---|---|
committer | Emmanuel Odeke <emmanuel@orijtech.com> | 2021-03-16 00:27:31 +0000 |
commit | f02a26bed0f21de7aeef7a60cf62dac2e3dab737 (patch) | |
tree | 8e944aa73d315e365b393cf86179bd7a2050350a /src/time/format.go | |
parent | a9b3c4bd0602f95afc58328d9953534f5e5fe4f6 (diff) | |
download | go-f02a26bed0f21de7aeef7a60cf62dac2e3dab737.tar.gz go-f02a26bed0f21de7aeef7a60cf62dac2e3dab737.zip |
time: support "," as separator for fractional seconds
Accepts comma "," as a separator for fractional seconds
hence we now accept:
* 2006-01-02 15:04:05,999999999 -0700 MST
* Mon Jan _2 15:04:05,120007 2006
* Mon Jan 2 15:04:05,120007 2006
This change follows the recommendations of ISO 8601 per
https://en.wikipedia.org/wiki/ISO_8601#cite_note-26
which states
ISO 8601:2004(E), ISO, 2004-12-01, "4.2.2.4 ...
the decimal fraction shall be divided from the integer
part by the decimal sign specified in ISO 31-0, i.e.
the comma [,] or full stop [.]. Of these, the comma
is the preferred sign."
Unfortunately, I couldn't directly access the ISO 8601 document
because suddenly it is behind a paywall on the ISO website,
charging CHF 158 (USD 179) for 38 pages :-(
However, this follows publicly available cited literature, as well
as the recommendations from the proposal approval.
Fixes #6189
Updates #27746
Updates #26002
Updates #36145
Updates #43813
Fixes #43823
Change-Id: Ibe96064e8ee27c239be78c880fa561a1a41e190c
Reviewed-on: https://go-review.googlesource.com/c/go/+/300996
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Rob Pike <r@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/time/format.go')
-rw-r--r-- | src/time/format.go | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/src/time/format.go b/src/time/format.go index c4f3358f59..7586035872 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -26,13 +26,14 @@ import "errors" // compatibility with fixed-width Unix time formats. // // A decimal point followed by one or more zeros represents a fractional -// second, printed to the given number of decimal places. A decimal point -// followed by one or more nines represents a fractional second, printed to -// the given number of decimal places, with trailing zeros removed. +// second, printed to the given number of decimal places. +// Either a comma or decimal point followed by one or more nines represents +// a fractional second, printed to the given number of decimal places, with +// trailing zeros removed. // When parsing (only), the input may contain a fractional second // field immediately after the seconds field, even if the layout does not -// signify its presence. In that case a decimal point followed by a maximal -// series of digits is parsed as a fractional second. +// signify its presence. In that case either a comma or a decimal point +// followed by a maximal series of digits is parsed as a fractional second. // // Numeric time zone offsets format as follows: // -0700 ±hhmm @@ -261,7 +262,7 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) { return layout[0:i], stdISO8601ShortTZ, layout[i+3:] } - case '.': // .000 or .999 - repeated digits for fractional seconds. + case '.', ',': // ,000, or .000, or ,999, or .999 - repeated digits for fractional seconds. if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') { ch := layout[i+1] j := i + 1 @@ -484,9 +485,10 @@ func (t Time) String() string { // desired output. The same display rules will then be applied to the time // value. // -// A fractional second is represented by adding a period and zeros -// to the end of the seconds section of layout string, as in "15:04:05.000" -// to format a time stamp with millisecond precision. +// A fractional second is represented by adding either a comma or a +// period and zeros to the end of the seconds section of layout string, +// as in "15:04:05,000" or "15:04:05.000" to format a time stamp with +// millisecond precision. // // Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard // and convenient representations of the reference time. For more information @@ -940,7 +942,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) } // Special case: do we have a fractional second but no // fractional second in the format? - if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) { + if len(value) >= 2 && commaOrPeriod(value[0]) && isDigit(value, 1) { _, std, _ = nextStdChunk(layout) std &= stdMask if std == stdFracSecond0 || std == stdFracSecond9 { @@ -1070,7 +1072,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) value = value[ndigit:] case stdFracSecond9: - if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] { + if len(value) < 2 || !commaOrPeriod(value[0]) || value[1] < '0' || '9' < value[1] { // Fractional second omitted. break } @@ -1279,8 +1281,12 @@ func parseSignedOffset(value string) int { return len(value) - len(rem) } +func commaOrPeriod(b byte) bool { + return b == '.' || b == ',' +} + func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) { - if value[0] != '.' { + if !commaOrPeriod(value[0]) { err = errBad return } |