mirror of
https://github.com/golang/go
synced 2024-11-21 23:34:42 -07:00
don't worry about the number of spaces when parsing.
allow an underscore to stand for a space or digit if the following number is >=10. R=rsc CC=golang-dev https://golang.org/cl/186115
This commit is contained in:
parent
ccbcefe2b6
commit
63d639295c
@ -2,6 +2,7 @@ package time
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"once"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@ -14,12 +15,16 @@ const (
|
|||||||
|
|
||||||
// These are predefined layouts for use in Time.Format.
|
// These are predefined layouts for use in Time.Format.
|
||||||
// The standard time used in the layouts is:
|
// The standard time used in the layouts is:
|
||||||
// Mon Jan 2 15:04:05 MST 2006 (MST is GMT-0700)
|
// Mon Jan 2 15:04:05 MST 2006 (MST is GMT-0700)
|
||||||
// which is Unix time 1136243045.
|
// which is Unix time 1136243045.
|
||||||
// (Think of it as 01/02 03:04:05PM '06 -0700.)
|
// (Think of it as 01/02 03:04:05PM '06 -0700.)
|
||||||
|
// An underscore _ represents a space that
|
||||||
|
// may be replaced by a digit if the following number
|
||||||
|
// (a day) has two digits; for compatibility with
|
||||||
|
// fixed-width Unix time formats.
|
||||||
const (
|
const (
|
||||||
ANSIC = "Mon Jan 2 15:04:05 2006"
|
ANSIC = "Mon Jan _2 15:04:05 2006"
|
||||||
UnixDate = "Mon Jan 2 15:04:05 MST 2006"
|
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
|
||||||
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
|
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
|
||||||
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
|
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
|
||||||
Kitchen = "3:04PM"
|
Kitchen = "3:04PM"
|
||||||
@ -36,6 +41,7 @@ const (
|
|||||||
stdLongWeekDay = "Monday"
|
stdLongWeekDay = "Monday"
|
||||||
stdWeekDay = "Mon"
|
stdWeekDay = "Mon"
|
||||||
stdDay = "2"
|
stdDay = "2"
|
||||||
|
stdUnderDay = "_2"
|
||||||
stdZeroDay = "02"
|
stdZeroDay = "02"
|
||||||
stdHour = "15"
|
stdHour = "15"
|
||||||
stdHour12 = "3"
|
stdHour12 = "3"
|
||||||
@ -118,20 +124,24 @@ func charType(c uint8) int {
|
|||||||
switch {
|
switch {
|
||||||
case '0' <= c && c <= '9':
|
case '0' <= c && c <= '9':
|
||||||
return numeric
|
return numeric
|
||||||
|
case c == '_': // underscore; treated like a number when printing
|
||||||
|
return numeric
|
||||||
case 'a' <= c && c < 'z', 'A' <= c && c <= 'Z':
|
case 'a' <= c && c < 'z', 'A' <= c && c <= 'Z':
|
||||||
return alphabetic
|
return alphabetic
|
||||||
}
|
}
|
||||||
return separator
|
return separator
|
||||||
}
|
}
|
||||||
|
|
||||||
func zeroPad(i int) string {
|
func pad(i int, padding string) string {
|
||||||
s := strconv.Itoa(i)
|
s := strconv.Itoa(i)
|
||||||
if i < 10 {
|
if i < 10 {
|
||||||
s = "0" + s
|
s = padding + s
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func zeroPad(i int) string { return pad(i, "0") }
|
||||||
|
|
||||||
// Format returns a textual representation of the time value formatted
|
// Format returns a textual representation of the time value formatted
|
||||||
// according to layout. The layout defines the format by showing the
|
// according to layout. The layout defines the format by showing the
|
||||||
// representation of a standard time, which is then used to describe
|
// representation of a standard time, which is then used to describe
|
||||||
@ -168,6 +178,8 @@ func (t *Time) Format(layout string) string {
|
|||||||
p = longDayNames[t.Weekday]
|
p = longDayNames[t.Weekday]
|
||||||
case stdDay:
|
case stdDay:
|
||||||
p = strconv.Itoa(t.Day)
|
p = strconv.Itoa(t.Day)
|
||||||
|
case stdUnderDay:
|
||||||
|
p = pad(t.Day, " ")
|
||||||
case stdZeroDay:
|
case stdZeroDay:
|
||||||
p = zeroPad(t.Day)
|
p = zeroPad(t.Day)
|
||||||
case stdHour:
|
case stdHour:
|
||||||
@ -250,6 +262,21 @@ func (e *ParseError) String() string {
|
|||||||
strconv.Quote(e.Value) + e.Message
|
strconv.Quote(e.Value) + e.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To simplify comparison, collapse an initial run of spaces into a single space.
|
||||||
|
func collapseSpaces(s string) string {
|
||||||
|
if len(s) <= 1 || s[0] != ' ' {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
for i = 1; i < len(s); i++ {
|
||||||
|
if s[i] != ' ' {
|
||||||
|
return s[i-1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse parses a formatted string and returns the time value it represents.
|
// Parse parses a formatted string and returns the time value it represents.
|
||||||
// The layout defines the format by showing the representation of a standard
|
// The layout defines the format by showing the representation of a standard
|
||||||
// time, which is then used to describe the string to be parsed. Predefined
|
// time, which is then used to describe the string to be parsed. Predefined
|
||||||
@ -296,15 +323,21 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
|
|||||||
}
|
}
|
||||||
p := value[0:i]
|
p := value[0:i]
|
||||||
value = value[i:]
|
value = value[i:]
|
||||||
// Separators must match except possibly for a following minus sign (for negative years)
|
// Separators must match but:
|
||||||
|
// - initial run of spaces is treated as a single space
|
||||||
|
// - there could be a following minus sign for negative years
|
||||||
if pieceType == separator {
|
if pieceType == separator {
|
||||||
if len(p) != len(reference) {
|
if len(p) != len(reference) {
|
||||||
// must be exactly a following minus sign
|
// must be exactly a following minus sign
|
||||||
if len(p) != len(reference)+1 || p[len(p)-1] != '-' {
|
pp := collapseSpaces(p)
|
||||||
return nil, &ParseError{Layout: alayout, Value: avalue, Message: formatErr + alayout}
|
rr := collapseSpaces(reference)
|
||||||
|
if pp != rr {
|
||||||
|
if len(pp) != len(rr)+1 || p[len(pp)-1] != '-' {
|
||||||
|
return nil, &ParseError{Layout: alayout, Value: avalue, Message: formatErr + alayout}
|
||||||
|
}
|
||||||
|
nextIsYear = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
nextIsYear = true
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var err os.Error
|
var err os.Error
|
||||||
@ -335,7 +368,7 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
|
|||||||
t.Weekday, err = lookup(shortDayNames, p)
|
t.Weekday, err = lookup(shortDayNames, p)
|
||||||
case stdLongWeekDay:
|
case stdLongWeekDay:
|
||||||
t.Weekday, err = lookup(longDayNames, p)
|
t.Weekday, err = lookup(longDayNames, p)
|
||||||
case stdDay, stdZeroDay:
|
case stdDay, stdUnderDay, stdZeroDay:
|
||||||
t.Day, err = strconv.Atoi(p)
|
t.Day, err = strconv.Atoi(p)
|
||||||
if t.Day < 0 || 31 < t.Day {
|
if t.Day < 0 || 31 < t.Day {
|
||||||
// TODO: be more thorough in date check?
|
// TODO: be more thorough in date check?
|
||||||
@ -422,6 +455,7 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
|
|||||||
// It's a valid format.
|
// It's a valid format.
|
||||||
t.Zone = p
|
t.Zone = p
|
||||||
// Can we find it in the table?
|
// Can we find it in the table?
|
||||||
|
once.Do(setupZone)
|
||||||
for _, z := range zones {
|
for _, z := range zones {
|
||||||
if p == z.zone.name {
|
if p == z.zone.name {
|
||||||
t.ZoneOffset = z.zone.utcoff
|
t.ZoneOffset = z.zone.utcoff
|
||||||
|
@ -165,6 +165,9 @@ var parseTests = []ParseTest{
|
|||||||
ParseTest{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true},
|
ParseTest{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true},
|
||||||
ParseTest{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true},
|
ParseTest{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true},
|
||||||
ParseTest{"ISO8601", ISO8601, "2010-02-04T21:00:57-0800", true, false},
|
ParseTest{"ISO8601", ISO8601, "2010-02-04T21:00:57-0800", true, false},
|
||||||
|
// Amount of white space should not matter.
|
||||||
|
ParseTest{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true},
|
||||||
|
ParseTest{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
func TestParse(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user