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
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index 8f81df9..745d9fb 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"once"
 	"os"
 	"strconv"
 )
@@ -14,12 +15,16 @@
 
 // These are predefined layouts for use in Time.Format.
 // 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.
 // (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 (
-	ANSIC    = "Mon Jan  2 15:04:05 2006"
-	UnixDate = "Mon Jan  2 15:04:05 MST 2006"
+	ANSIC    = "Mon Jan _2 15:04:05 2006"
+	UnixDate = "Mon Jan _2 15:04:05 MST 2006"
 	RFC850   = "Monday, 02-Jan-06 15:04:05 MST"
 	RFC1123  = "Mon, 02 Jan 2006 15:04:05 MST"
 	Kitchen  = "3:04PM"
@@ -36,6 +41,7 @@
 	stdLongWeekDay = "Monday"
 	stdWeekDay     = "Mon"
 	stdDay         = "2"
+	stdUnderDay    = "_2"
 	stdZeroDay     = "02"
 	stdHour        = "15"
 	stdHour12      = "3"
@@ -118,20 +124,24 @@
 	switch {
 	case '0' <= c && c <= '9':
 		return numeric
+	case c == '_': // underscore; treated like a number when printing
+		return numeric
 	case 'a' <= c && c < 'z', 'A' <= c && c <= 'Z':
 		return alphabetic
 	}
 	return separator
 }
 
-func zeroPad(i int) string {
+func pad(i int, padding string) string {
 	s := strconv.Itoa(i)
 	if i < 10 {
-		s = "0" + s
+		s = padding + s
 	}
 	return s
 }
 
+func zeroPad(i int) string { return pad(i, "0") }
+
 // Format returns a textual representation of the time value formatted
 // according to layout.  The layout defines the format by showing the
 // representation of a standard time, which is then used to describe
@@ -168,6 +178,8 @@
 			p = longDayNames[t.Weekday]
 		case stdDay:
 			p = strconv.Itoa(t.Day)
+		case stdUnderDay:
+			p = pad(t.Day, " ")
 		case stdZeroDay:
 			p = zeroPad(t.Day)
 		case stdHour:
@@ -250,6 +262,21 @@
 		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.
 // 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
@@ -296,15 +323,21 @@
 		}
 		p := value[0: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 len(p) != len(reference) {
 				// must be exactly a following minus sign
-				if len(p) != len(reference)+1 || p[len(p)-1] != '-' {
-					return nil, &ParseError{Layout: alayout, Value: avalue, Message: formatErr + alayout}
+				pp := collapseSpaces(p)
+				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
@@ -335,7 +368,7 @@
 			t.Weekday, err = lookup(shortDayNames, p)
 		case stdLongWeekDay:
 			t.Weekday, err = lookup(longDayNames, p)
-		case stdDay, stdZeroDay:
+		case stdDay, stdUnderDay, stdZeroDay:
 			t.Day, err = strconv.Atoi(p)
 			if t.Day < 0 || 31 < t.Day {
 				// TODO: be more thorough in date check?
@@ -422,6 +455,7 @@
 			// It's a valid format.
 			t.Zone = p
 			// Can we find it in the table?
+			once.Do(setupZone)
 			for _, z := range zones {
 				if p == z.zone.name {
 					t.ZoneOffset = z.zone.utcoff
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index dab6d20..5036ceb 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -165,6 +165,9 @@
 	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{"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) {