diff options
Diffstat (limited to 'libgo/go/time/format.go')
-rw-r--r-- | libgo/go/time/format.go | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go index e616feb048..b903e1485c 100644 --- a/libgo/go/time/format.go +++ b/libgo/go/time/format.go @@ -23,7 +23,7 @@ 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 +// 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. // When parsing (only), the input may contain a fractional second @@ -37,11 +37,18 @@ import "errors" // -07 ±hh // Replacing the sign in the format with a Z triggers // the ISO 8601 behavior of printing Z instead of an -// offset for the UTC zone. Thus: +// offset for the UTC zone. Thus: // Z0700 Z or ±hhmm // Z07:00 Z or ±hh:mm // Z07 Z or ±hh // +// The recognized day of week formats are "Mon" and "Monday". +// The recognized month formats are "Jan" and "January". +// +// Text in the format string that is not recognized as part of the reference +// time is echoed verbatim during Format and expected to appear verbatim +// in the input to Parse. +// // The executable example for time.Format demonstrates the working // of the layout string in detail and is a good reference. // @@ -51,6 +58,9 @@ import "errors" // use of "GMT" in that case. // In general RFC1123Z should be used instead of RFC1123 for servers // that insist on that format, and RFC3339 should be preferred for new protocols. +// RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting; +// when used with time.Parse they do not accept all the time formats +// permitted by the RFCs. const ( ANSIC = "Mon Jan _2 15:04:05 2006" UnixDate = "Mon Jan _2 15:04:05 MST 2006" @@ -551,7 +561,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte { b = append(b, "am"...) } case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ: - // Ugly special case. We cheat and take the "Z" variants + // Ugly special case. We cheat and take the "Z" variants // to mean "the time zone as formatted for ISO 8601". if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) { b = append(b, 'Z') @@ -841,6 +851,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) sec, value, err = getnum(value, std == stdZeroSecond) if sec < 0 || 60 <= sec { rangeErrString = "second" + break } // Special case: do we have a fractional second but no // fractional second in the format? @@ -1001,7 +1012,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) } // Validate the day of the month. - if day > daysIn(Month(month), year) { + if day < 1 || day > daysIn(Month(month), year) { return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"} } @@ -1017,12 +1028,12 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) // If that zone was in effect at the given time, use it. name, offset, _, _, _ := local.lookup(t.sec + internalToUnix) if offset == zoneOffset && (zoneName == "" || name == zoneName) { - t.loc = local + t.setLoc(local) return t, nil } // Otherwise create fake zone to record offset. - t.loc = FixedZone(zoneName, zoneOffset) + t.setLoc(FixedZone(zoneName, zoneOffset)) return t, nil } @@ -1033,7 +1044,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix) if ok { t.sec -= int64(offset) - t.loc = local + t.setLoc(local) return t, nil } @@ -1042,7 +1053,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT. offset *= 3600 } - t.loc = FixedZone(zoneName, offset) + t.setLoc(FixedZone(zoneName, offset)) return t, nil } @@ -1090,8 +1101,9 @@ func parseTimeZone(value string) (length int, ok bool) { if value[4] == 'T' { return 5, true } - case 4: // Must end in T to match. - if value[3] == 'T' { + case 4: + // Must end in T, except one special case. + if value[3] == 'T' || value[:4] == "WITA" { return 4, true } case 3: @@ -1170,6 +1182,37 @@ func leadingInt(s string) (x int64, rem string, err error) { return x, s[i:], nil } +// leadingFraction consumes the leading [0-9]* from s. +// It is used only for fractions, so does not return an error on overflow, +// it just stops accumulating precision. +func leadingFraction(s string) (x int64, scale float64, rem string) { + i := 0 + scale = 1 + overflow := false + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if overflow { + continue + } + if x > (1<<63-1)/10 { + // It's possible for overflow to give a positive number, so take care. + overflow = true + continue + } + y := x*10 + int64(c) - '0' + if y < 0 { + overflow = true + continue + } + x = y + scale *= 10 + } + return x, scale, s[i:] +} + var unitMap = map[string]int64{ "ns": int64(Nanosecond), "us": int64(Microsecond), @@ -1232,13 +1275,7 @@ func ParseDuration(s string) (Duration, error) { if s != "" && s[0] == '.' { s = s[1:] pl := len(s) - f, s, err = leadingInt(s) - if err != nil { - return 0, errors.New("time: invalid duration " + orig) - } - for n := pl - len(s); n > 0; n-- { - scale *= 10 - } + f, scale, s = leadingFraction(s) post = pl != len(s) } if !pre && !post { |