summaryrefslogtreecommitdiff
path: root/libgo/go/time/format.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/time/format.go')
-rw-r--r--libgo/go/time/format.go71
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 {