src/pkg/time/format.go - The Go Programming Language

Golang

Source file src/pkg/time/format.go

     1	// Copyright 2010 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package time
     6	
     7	import "errors"
     8	
     9	// These are predefined layouts for use in Time.Format.
    10	// The standard time used in the layouts is:
    11	//	Mon Jan 2 15:04:05 MST 2006
    12	// which is Unix time 1136243045. Since MST is GMT-0700,
    13	// the standard time can be thought of as
    14	//	01/02 03:04:05PM '06 -0700
    15	// To define your own format, write down what the standard time would look
    16	// like formatted your way; see the values of constants like ANSIC,
    17	// StampMicro or Kitchen for examples.
    18	//
    19	// Within the format string, an underscore _ represents a space that may be
    20	// replaced by a digit if the following number (a day) has two digits; for
    21	// compatibility with fixed-width Unix time formats.
    22	//
    23	// A decimal point followed by one or more zeros represents a fractional
    24	// second, printed to the given number of decimal places.  A decimal point
    25	// followed by one or more nines represents a fractional second, printed to
    26	// the given number of decimal places, with trailing zeros removed.
    27	// When parsing (only), the input may contain a fractional second
    28	// field immediately after the seconds field, even if the layout does not
    29	// signify its presence. In that case a decimal point followed by a maximal
    30	// series of digits is parsed as a fractional second.
    31	//
    32	// Numeric time zone offsets format as follows:
    33	//	-0700  ±hhmm
    34	//	-07:00 ±hh:mm
    35	// Replacing the sign in the format with a Z triggers
    36	// the ISO 8601 behavior of printing Z instead of an
    37	// offset for the UTC zone.  Thus:
    38	//	Z0700  Z or ±hhmm
    39	//	Z07:00 Z or ±hh:mm
    40	const (
    41		ANSIC       = "Mon Jan _2 15:04:05 2006"
    42		UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    43		RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    44		RFC822      = "02 Jan 06 15:04 MST"
    45		RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
    46		RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    47		RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    48		RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
    49		RFC3339     = "2006-01-02T15:04:05Z07:00"
    50		RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    51		Kitchen     = "3:04PM"
    52		// Handy time stamps.
    53		Stamp      = "Jan _2 15:04:05"
    54		StampMilli = "Jan _2 15:04:05.000"
    55		StampMicro = "Jan _2 15:04:05.000000"
    56		StampNano  = "Jan _2 15:04:05.000000000"
    57	)
    58	
    59	const (
    60		stdLongMonth      = "January"
    61		stdMonth          = "Jan"
    62		stdNumMonth       = "1"
    63		stdZeroMonth      = "01"
    64		stdLongWeekDay    = "Monday"
    65		stdWeekDay        = "Mon"
    66		stdDay            = "2"
    67		stdUnderDay       = "_2"
    68		stdZeroDay        = "02"
    69		stdHour           = "15"
    70		stdHour12         = "3"
    71		stdZeroHour12     = "03"
    72		stdMinute         = "4"
    73		stdZeroMinute     = "04"
    74		stdSecond         = "5"
    75		stdZeroSecond     = "05"
    76		stdLongYear       = "2006"
    77		stdYear           = "06"
    78		stdPM             = "PM"
    79		stdpm             = "pm"
    80		stdTZ             = "MST"
    81		stdISO8601TZ      = "Z0700"  // prints Z for UTC
    82		stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
    83		stdNumTZ          = "-0700"  // always numeric
    84		stdNumShortTZ     = "-07"    // always numeric
    85		stdNumColonTZ     = "-07:00" // always numeric
    86	)
    87	
    88	// nextStdChunk finds the first occurrence of a std string in
    89	// layout and returns the text before, the std string, and the text after.
    90	func nextStdChunk(layout string) (prefix, std, suffix string) {
    91		for i := 0; i < len(layout); i++ {
    92			switch layout[i] {
    93			case 'J': // January, Jan
    94				if len(layout) >= i+7 && layout[i:i+7] == stdLongMonth {
    95					return layout[0:i], stdLongMonth, layout[i+7:]
    96				}
    97				if len(layout) >= i+3 && layout[i:i+3] == stdMonth {
    98					return layout[0:i], stdMonth, layout[i+3:]
    99				}
   100	
   101			case 'M': // Monday, Mon, MST
   102				if len(layout) >= i+6 && layout[i:i+6] == stdLongWeekDay {
   103					return layout[0:i], stdLongWeekDay, layout[i+6:]
   104				}
   105				if len(layout) >= i+3 {
   106					if layout[i:i+3] == stdWeekDay {
   107						return layout[0:i], stdWeekDay, layout[i+3:]
   108					}
   109					if layout[i:i+3] == stdTZ {
   110						return layout[0:i], stdTZ, layout[i+3:]
   111					}
   112				}
   113	
   114			case '0': // 01, 02, 03, 04, 05, 06
   115				if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
   116					return layout[0:i], layout[i : i+2], layout[i+2:]
   117				}
   118	
   119			case '1': // 15, 1
   120				if len(layout) >= i+2 && layout[i+1] == '5' {
   121					return layout[0:i], stdHour, layout[i+2:]
   122				}
   123				return layout[0:i], stdNumMonth, layout[i+1:]
   124	
   125			case '2': // 2006, 2
   126				if len(layout) >= i+4 && layout[i:i+4] == stdLongYear {
   127					return layout[0:i], stdLongYear, layout[i+4:]
   128				}
   129				return layout[0:i], stdDay, layout[i+1:]
   130	
   131			case '_': // _2
   132				if len(layout) >= i+2 && layout[i+1] == '2' {
   133					return layout[0:i], stdUnderDay, layout[i+2:]
   134				}
   135	
   136			case '3', '4', '5': // 3, 4, 5
   137				return layout[0:i], layout[i : i+1], layout[i+1:]
   138	
   139			case 'P': // PM
   140				if len(layout) >= i+2 && layout[i+1] == 'M' {
   141					return layout[0:i], layout[i : i+2], layout[i+2:]
   142				}
   143	
   144			case 'p': // pm
   145				if len(layout) >= i+2 && layout[i+1] == 'm' {
   146					return layout[0:i], layout[i : i+2], layout[i+2:]
   147				}
   148	
   149			case '-': // -0700, -07:00, -07
   150				if len(layout) >= i+5 && layout[i:i+5] == stdNumTZ {
   151					return layout[0:i], layout[i : i+5], layout[i+5:]
   152				}
   153				if len(layout) >= i+6 && layout[i:i+6] == stdNumColonTZ {
   154					return layout[0:i], layout[i : i+6], layout[i+6:]
   155				}
   156				if len(layout) >= i+3 && layout[i:i+3] == stdNumShortTZ {
   157					return layout[0:i], layout[i : i+3], layout[i+3:]
   158				}
   159			case 'Z': // Z0700, Z07:00
   160				if len(layout) >= i+5 && layout[i:i+5] == stdISO8601TZ {
   161					return layout[0:i], layout[i : i+5], layout[i+5:]
   162				}
   163				if len(layout) >= i+6 && layout[i:i+6] == stdISO8601ColonTZ {
   164					return layout[0:i], layout[i : i+6], layout[i+6:]
   165				}
   166			case '.': // .000 or .999 - repeated digits for fractional seconds.
   167				if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
   168					ch := layout[i+1]
   169					j := i + 1
   170					for j < len(layout) && layout[j] == ch {
   171						j++
   172					}
   173					// String of digits must end here - only fractional second is all digits.
   174					if !isDigit(layout, j) {
   175						return layout[0:i], layout[i:j], layout[j:]
   176					}
   177				}
   178			}
   179		}
   180		return layout, "", ""
   181	}
   182	
   183	var longDayNames = []string{
   184		"Sunday",
   185		"Monday",
   186		"Tuesday",
   187		"Wednesday",
   188		"Thursday",
   189		"Friday",
   190		"Saturday",
   191	}
   192	
   193	var shortDayNames = []string{
   194		"Sun",
   195		"Mon",
   196		"Tue",
   197		"Wed",
   198		"Thu",
   199		"Fri",
   200		"Sat",
   201	}
   202	
   203	var shortMonthNames = []string{
   204		"---",
   205		"Jan",
   206		"Feb",
   207		"Mar",
   208		"Apr",
   209		"May",
   210		"Jun",
   211		"Jul",
   212		"Aug",
   213		"Sep",
   214		"Oct",
   215		"Nov",
   216		"Dec",
   217	}
   218	
   219	var longMonthNames = []string{
   220		"---",
   221		"January",
   222		"February",
   223		"March",
   224		"April",
   225		"May",
   226		"June",
   227		"July",
   228		"August",
   229		"September",
   230		"October",
   231		"November",
   232		"December",
   233	}
   234	
   235	// match returns true if s1 and s2 match ignoring case.
   236	// It is assumed s1 and s2 are the same length.
   237	func match(s1, s2 string) bool {
   238		for i := 0; i < len(s1); i++ {
   239			c1 := s1[i]
   240			c2 := s2[i]
   241			if c1 != c2 {
   242				// Switch to lower-case; 'a'-'A' is known to be a single bit.
   243				c1 |= 'a' - 'A'
   244				c2 |= 'a' - 'A'
   245				if c1 != c2 || c1 < 'a' || c1 > 'z' {
   246					return false
   247				}
   248			}
   249		}
   250		return true
   251	}
   252	
   253	func lookup(tab []string, val string) (int, string, error) {
   254		for i, v := range tab {
   255			if len(val) >= len(v) && match(val[0:len(v)], v) {
   256				return i, val[len(v):], nil
   257			}
   258		}
   259		return -1, val, errBad
   260	}
   261	
   262	// Duplicates functionality in strconv, but avoids dependency.
   263	func itoa(x int) string {
   264		var buf [32]byte
   265		n := len(buf)
   266		if x == 0 {
   267			return "0"
   268		}
   269		u := uint(x)
   270		if x < 0 {
   271			u = -u
   272		}
   273		for u > 0 {
   274			n--
   275			buf[n] = byte(u%10 + '0')
   276			u /= 10
   277		}
   278		if x < 0 {
   279			n--
   280			buf[n] = '-'
   281		}
   282		return string(buf[n:])
   283	}
   284	
   285	// Never printed, just needs to be non-nil for return by atoi.
   286	var atoiError = errors.New("time: invalid number")
   287	
   288	// Duplicates functionality in strconv, but avoids dependency.
   289	func atoi(s string) (x int, err error) {
   290		neg := false
   291		if s != "" && s[0] == '-' {
   292			neg = true
   293			s = s[1:]
   294		}
   295		x, rem, err := leadingInt(s)
   296		if err != nil || rem != "" {
   297			return 0, atoiError
   298		}
   299		if neg {
   300			x = -x
   301		}
   302		return x, nil
   303	}
   304	
   305	func pad(i int, padding string) string {
   306		s := itoa(i)
   307		if i < 10 {
   308			s = padding + s
   309		}
   310		return s
   311	}
   312	
   313	func zeroPad(i int) string { return pad(i, "0") }
   314	
   315	// formatNano formats a fractional second, as nanoseconds.
   316	func formatNano(nanosec, n int, trim bool) string {
   317		// User might give us bad data. Make sure it's positive and in range.
   318		// They'll get nonsense output but it will have the right format.
   319		s := itoa(int(uint(nanosec) % 1e9))
   320		// Zero pad left without fmt.
   321		if len(s) < 9 {
   322			s = "000000000"[:9-len(s)] + s
   323		}
   324		if n > 9 {
   325			n = 9
   326		}
   327		if trim {
   328			for n > 0 && s[n-1] == '0' {
   329				n--
   330			}
   331			if n == 0 {
   332				return ""
   333			}
   334		}
   335		return "." + s[:n]
   336	}
   337	
   338	// String returns the time formatted using the format string
   339	//	"2006-01-02 15:04:05.999999999 -0700 MST"
   340	func (t Time) String() string {
   341		return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
   342	}
   343	
   344	type buffer []byte
   345	
   346	func (b *buffer) WriteString(s string) {
   347		*b = append(*b, s...)
   348	}
   349	
   350	func (b *buffer) String() string {
   351		return string([]byte(*b))
   352	}
   353	
   354	// Format returns a textual representation of the time value formatted
   355	// according to layout.  The layout defines the format by showing the
   356	// representation of the standard time,
   357	//	Mon Jan 2 15:04:05 -0700 MST 2006
   358	// which is then used to describe the time to be formatted. Predefined
   359	// layouts ANSIC, UnixDate, RFC3339 and others describe standard
   360	// representations. For more information about the formats and the
   361	// definition of the standard time, see the documentation for ANSIC.
   362	func (t Time) Format(layout string) string {
   363		var (
   364			year  int = -1
   365			month Month
   366			day   int
   367			hour  int = -1
   368			min   int
   369			sec   int
   370			b     buffer
   371		)
   372		// Each iteration generates one std value.
   373		for {
   374			prefix, std, suffix := nextStdChunk(layout)
   375			b.WriteString(prefix)
   376			if std == "" {
   377				break
   378			}
   379	
   380			// Compute year, month, day if needed.
   381			if year < 0 {
   382				// Jan 01 02 2006
   383				if a, z := std[0], std[len(std)-1]; a == 'J' || a == 'j' || z == '1' || z == '2' || z == '6' {
   384					year, month, day = t.Date()
   385				}
   386			}
   387	
   388			// Compute hour, minute, second if needed.
   389			if hour < 0 {
   390				// 03 04 05 15 pm
   391				if z := std[len(std)-1]; z == '3' || z == '4' || z == '5' || z == 'm' || z == 'M' {
   392					hour, min, sec = t.Clock()
   393				}
   394			}
   395	
   396			var p string
   397			switch std {
   398			case stdYear:
   399				p = zeroPad(year % 100)
   400			case stdLongYear:
   401				// Pad year to at least 4 digits.
   402				p = itoa(year)
   403				switch {
   404				case year <= -1000:
   405					// ok
   406				case year <= -100:
   407					p = p[:1] + "0" + p[1:]
   408				case year <= -10:
   409					p = p[:1] + "00" + p[1:]
   410				case year < 0:
   411					p = p[:1] + "000" + p[1:]
   412				case year < 10:
   413					p = "000" + p
   414				case year < 100:
   415					p = "00" + p
   416				case year < 1000:
   417					p = "0" + p
   418				}
   419			case stdMonth:
   420				p = month.String()[:3]
   421			case stdLongMonth:
   422				p = month.String()
   423			case stdNumMonth:
   424				p = itoa(int(month))
   425			case stdZeroMonth:
   426				p = zeroPad(int(month))
   427			case stdWeekDay:
   428				p = t.Weekday().String()[:3]
   429			case stdLongWeekDay:
   430				p = t.Weekday().String()
   431			case stdDay:
   432				p = itoa(day)
   433			case stdUnderDay:
   434				p = pad(day, " ")
   435			case stdZeroDay:
   436				p = zeroPad(day)
   437			case stdHour:
   438				p = zeroPad(hour)
   439			case stdHour12:
   440				// Noon is 12PM, midnight is 12AM.
   441				hr := hour % 12
   442				if hr == 0 {
   443					hr = 12
   444				}
   445				p = itoa(hr)
   446			case stdZeroHour12:
   447				// Noon is 12PM, midnight is 12AM.
   448				hr := hour % 12
   449				if hr == 0 {
   450					hr = 12
   451				}
   452				p = zeroPad(hr)
   453			case stdMinute:
   454				p = itoa(min)
   455			case stdZeroMinute:
   456				p = zeroPad(min)
   457			case stdSecond:
   458				p = itoa(sec)
   459			case stdZeroSecond:
   460				p = zeroPad(sec)
   461			case stdPM:
   462				if hour >= 12 {
   463					p = "PM"
   464				} else {
   465					p = "AM"
   466				}
   467			case stdpm:
   468				if hour >= 12 {
   469					p = "pm"
   470				} else {
   471					p = "am"
   472				}
   473			case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
   474				// Ugly special case.  We cheat and take the "Z" variants
   475				// to mean "the time zone as formatted for ISO 8601".
   476				_, offset := t.Zone()
   477				if offset == 0 && std[0] == 'Z' {
   478					p = "Z"
   479					break
   480				}
   481				zone := offset / 60 // convert to minutes
   482				if zone < 0 {
   483					p = "-"
   484					zone = -zone
   485				} else {
   486					p = "+"
   487				}
   488				p += zeroPad(zone / 60)
   489				if std == stdISO8601ColonTZ || std == stdNumColonTZ {
   490					p += ":"
   491				}
   492				p += zeroPad(zone % 60)
   493			case stdTZ:
   494				name, offset := t.Zone()
   495				if name != "" {
   496					p = name
   497				} else {
   498					// No time zone known for this time, but we must print one.
   499					// Use the -0700 format.
   500					zone := offset / 60 // convert to minutes
   501					if zone < 0 {
   502						p = "-"
   503						zone = -zone
   504					} else {
   505						p = "+"
   506					}
   507					p += zeroPad(zone / 60)
   508					p += zeroPad(zone % 60)
   509				}
   510			default:
   511				if len(std) >= 2 && (std[0:2] == ".0" || std[0:2] == ".9") {
   512					p = formatNano(t.Nanosecond(), len(std)-1, std[1] == '9')
   513				}
   514			}
   515			b.WriteString(p)
   516			layout = suffix
   517		}
   518		return b.String()
   519	}
   520	
   521	var errBad = errors.New("bad value for field") // placeholder not passed to user
   522	
   523	// ParseError describes a problem parsing a time string.
   524	type ParseError struct {
   525		Layout     string
   526		Value      string
   527		LayoutElem string
   528		ValueElem  string
   529		Message    string
   530	}
   531	
   532	func quote(s string) string {
   533		return "\"" + s + "\""
   534	}
   535	
   536	// Error returns the string representation of a ParseError.
   537	func (e *ParseError) Error() string {
   538		if e.Message == "" {
   539			return "parsing time " +
   540				quote(e.Value) + " as " +
   541				quote(e.Layout) + ": cannot parse " +
   542				quote(e.ValueElem) + " as " +
   543				quote(e.LayoutElem)
   544		}
   545		return "parsing time " +
   546			quote(e.Value) + e.Message
   547	}
   548	
   549	// isDigit returns true if s[i] is a decimal digit, false if not or
   550	// if s[i] is out of range.
   551	func isDigit(s string, i int) bool {
   552		if len(s) <= i {
   553			return false
   554		}
   555		c := s[i]
   556		return '0' <= c && c <= '9'
   557	}
   558	
   559	// getnum parses s[0:1] or s[0:2] (fixed forces the latter)
   560	// as a decimal integer and returns the integer and the
   561	// remainder of the string.
   562	func getnum(s string, fixed bool) (int, string, error) {
   563		if !isDigit(s, 0) {
   564			return 0, s, errBad
   565		}
   566		if !isDigit(s, 1) {
   567			if fixed {
   568				return 0, s, errBad
   569			}
   570			return int(s[0] - '0'), s[1:], nil
   571		}
   572		return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
   573	}
   574	
   575	func cutspace(s string) string {
   576		for len(s) > 0 && s[0] == ' ' {
   577			s = s[1:]
   578		}
   579		return s
   580	}
   581	
   582	// skip removes the given prefix from value,
   583	// treating runs of space characters as equivalent.
   584	func skip(value, prefix string) (string, error) {
   585		for len(prefix) > 0 {
   586			if prefix[0] == ' ' {
   587				if len(value) > 0 && value[0] != ' ' {
   588					return "", errBad
   589				}
   590				prefix = cutspace(prefix)
   591				value = cutspace(value)
   592				continue
   593			}
   594			if len(value) == 0 || value[0] != prefix[0] {
   595				return "", errBad
   596			}
   597			prefix = prefix[1:]
   598			value = value[1:]
   599		}
   600		return value, nil
   601	}
   602	
   603	// Parse parses a formatted string and returns the time value it represents.
   604	// The layout defines the format by showing the representation of the
   605	// standard time,
   606	//	Mon Jan 2 15:04:05 -0700 MST 2006
   607	// which is then used to describe the string to be parsed. Predefined layouts
   608	// ANSIC, UnixDate, RFC3339 and others describe standard representations. For
   609	// more information about the formats and the definition of the standard
   610	// time, see the documentation for ANSIC.
   611	//
   612	// Elements omitted from the value are assumed to be zero or, when
   613	// zero is impossible, one, so parsing "3:04pm" returns the time
   614	// corresponding to Jan 1, year 0, 15:04:00 UTC.
   615	// Years must be in the range 0000..9999. The day of the week is checked
   616	// for syntax but it is otherwise ignored.
   617	func Parse(layout, value string) (Time, error) {
   618		alayout, avalue := layout, value
   619		rangeErrString := "" // set if a value is out of range
   620		amSet := false       // do we need to subtract 12 from the hour for midnight?
   621		pmSet := false       // do we need to add 12 to the hour?
   622	
   623		// Time being constructed.
   624		var (
   625			year       int
   626			month      int = 1 // January
   627			day        int = 1
   628			hour       int
   629			min        int
   630			sec        int
   631			nsec       int
   632			z          *Location
   633			zoneOffset int = -1
   634			zoneName   string
   635		)
   636	
   637		// Each iteration processes one std value.
   638		for {
   639			var err error
   640			prefix, std, suffix := nextStdChunk(layout)
   641			value, err = skip(value, prefix)
   642			if err != nil {
   643				return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
   644			}
   645			if len(std) == 0 {
   646				if len(value) != 0 {
   647					return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
   648				}
   649				break
   650			}
   651			layout = suffix
   652			var p string
   653			switch std {
   654			case stdYear:
   655				if len(value) < 2 {
   656					err = errBad
   657					break
   658				}
   659				p, value = value[0:2], value[2:]
   660				year, err = atoi(p)
   661				if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
   662					year += 1900
   663				} else {
   664					year += 2000
   665				}
   666			case stdLongYear:
   667				if len(value) < 4 || !isDigit(value, 0) {
   668					err = errBad
   669					break
   670				}
   671				p, value = value[0:4], value[4:]
   672				year, err = atoi(p)
   673			case stdMonth:
   674				month, value, err = lookup(shortMonthNames, value)
   675			case stdLongMonth:
   676				month, value, err = lookup(longMonthNames, value)
   677			case stdNumMonth, stdZeroMonth:
   678				month, value, err = getnum(value, std == stdZeroMonth)
   679				if month <= 0 || 12 < month {
   680					rangeErrString = "month"
   681				}
   682			case stdWeekDay:
   683				// Ignore weekday except for error checking.
   684				_, value, err = lookup(shortDayNames, value)
   685			case stdLongWeekDay:
   686				_, value, err = lookup(longDayNames, value)
   687			case stdDay, stdUnderDay, stdZeroDay:
   688				if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
   689					value = value[1:]
   690				}
   691				day, value, err = getnum(value, std == stdZeroDay)
   692				if day < 0 || 31 < day {
   693					rangeErrString = "day"
   694				}
   695			case stdHour:
   696				hour, value, err = getnum(value, false)
   697				if hour < 0 || 24 <= hour {
   698					rangeErrString = "hour"
   699				}
   700			case stdHour12, stdZeroHour12:
   701				hour, value, err = getnum(value, std == stdZeroHour12)
   702				if hour < 0 || 12 < hour {
   703					rangeErrString = "hour"
   704				}
   705			case stdMinute, stdZeroMinute:
   706				min, value, err = getnum(value, std == stdZeroMinute)
   707				if min < 0 || 60 <= min {
   708					rangeErrString = "minute"
   709				}
   710			case stdSecond, stdZeroSecond:
   711				sec, value, err = getnum(value, std == stdZeroSecond)
   712				if sec < 0 || 60 <= sec {
   713					rangeErrString = "second"
   714				}
   715				// Special case: do we have a fractional second but no
   716				// fractional second in the format?
   717				if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
   718					_, std, _ := nextStdChunk(layout)
   719					if len(std) > 0 && std[0] == '.' && isDigit(std, 1) {
   720						// Fractional second in the layout; proceed normally
   721						break
   722					}
   723					// No fractional second in the layout but we have one in the input.
   724					n := 2
   725					for ; n < len(value) && isDigit(value, n); n++ {
   726					}
   727					nsec, rangeErrString, err = parseNanoseconds(value, n)
   728					value = value[n:]
   729				}
   730			case stdPM:
   731				if len(value) < 2 {
   732					err = errBad
   733					break
   734				}
   735				p, value = value[0:2], value[2:]
   736				switch p {
   737				case "PM":
   738					pmSet = true
   739				case "AM":
   740					amSet = true
   741				default:
   742					err = errBad
   743				}
   744			case stdpm:
   745				if len(value) < 2 {
   746					err = errBad
   747					break
   748				}
   749				p, value = value[0:2], value[2:]
   750				switch p {
   751				case "pm":
   752					pmSet = true
   753				case "am":
   754					amSet = true
   755				default:
   756					err = errBad
   757				}
   758			case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
   759				if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' {
   760					value = value[1:]
   761					z = UTC
   762					break
   763				}
   764				var sign, hour, min string
   765				if std == stdISO8601ColonTZ || std == stdNumColonTZ {
   766					if len(value) < 6 {
   767						err = errBad
   768						break
   769					}
   770					if value[3] != ':' {
   771						err = errBad
   772						break
   773					}
   774					sign, hour, min, value = value[0:1], value[1:3], value[4:6], value[6:]
   775				} else if std == stdNumShortTZ {
   776					if len(value) < 3 {
   777						err = errBad
   778						break
   779					}
   780					sign, hour, min, value = value[0:1], value[1:3], "00", value[3:]
   781				} else {
   782					if len(value) < 5 {
   783						err = errBad
   784						break
   785					}
   786					sign, hour, min, value = value[0:1], value[1:3], value[3:5], value[5:]
   787				}
   788				var hr, mm int
   789				hr, err = atoi(hour)
   790				if err == nil {
   791					mm, err = atoi(min)
   792				}
   793				zoneOffset = (hr*60 + mm) * 60 // offset is in seconds
   794				switch sign[0] {
   795				case '+':
   796				case '-':
   797					zoneOffset = -zoneOffset
   798				default:
   799					err = errBad
   800				}
   801			case stdTZ:
   802				// Does it look like a time zone?
   803				if len(value) >= 3 && value[0:3] == "UTC" {
   804					z = UTC
   805					value = value[3:]
   806					break
   807				}
   808	
   809				if len(value) >= 3 && value[2] == 'T' {
   810					p, value = value[0:3], value[3:]
   811				} else if len(value) >= 4 && value[3] == 'T' {
   812					p, value = value[0:4], value[4:]
   813				} else {
   814					err = errBad
   815					break
   816				}
   817				for i := 0; i < len(p); i++ {
   818					if p[i] < 'A' || 'Z' < p[i] {
   819						err = errBad
   820					}
   821				}
   822				if err != nil {
   823					break
   824				}
   825				// It's a valid format.
   826				zoneName = p
   827			default:
   828				if len(value) < len(std) {
   829					err = errBad
   830					break
   831				}
   832				if len(std) >= 2 && std[0:2] == ".0" {
   833					nsec, rangeErrString, err = parseNanoseconds(value, len(std))
   834					value = value[len(std):]
   835				}
   836			}
   837			if rangeErrString != "" {
   838				return Time{}, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
   839			}
   840			if err != nil {
   841				return Time{}, &ParseError{alayout, avalue, std, value, ""}
   842			}
   843		}
   844		if pmSet && hour < 12 {
   845			hour += 12
   846		} else if amSet && hour == 12 {
   847			hour = 0
   848		}
   849	
   850		// TODO: be more aggressive checking day?
   851		if z != nil {
   852			return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
   853		}
   854	
   855		t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
   856		if zoneOffset != -1 {
   857			t.sec -= int64(zoneOffset)
   858	
   859			// Look for local zone with the given offset.
   860			// If that zone was in effect at the given time, use it.
   861			name, offset, _, _, _ := Local.lookup(t.sec + internalToUnix)
   862			if offset == zoneOffset && (zoneName == "" || name == zoneName) {
   863				t.loc = Local
   864				return t, nil
   865			}
   866	
   867			// Otherwise create fake zone to record offset.
   868			t.loc = FixedZone(zoneName, zoneOffset)
   869			return t, nil
   870		}
   871	
   872		if zoneName != "" {
   873			// Look for local zone with the given offset.
   874			// If that zone was in effect at the given time, use it.
   875			offset, _, ok := Local.lookupName(zoneName)
   876			if ok {
   877				name, off, _, _, _ := Local.lookup(t.sec + internalToUnix - int64(offset))
   878				if name == zoneName && off == offset {
   879					t.sec -= int64(offset)
   880					t.loc = Local
   881					return t, nil
   882				}
   883			}
   884	
   885			// Otherwise, create fake zone with unknown offset.
   886			t.loc = FixedZone(zoneName, 0)
   887			return t, nil
   888		}
   889	
   890		// Otherwise, fall back to UTC.
   891		return t, nil
   892	}
   893	
   894	func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
   895		if value[0] != '.' {
   896			err = errBad
   897			return
   898		}
   899		ns, err = atoi(value[1:nbytes])
   900		if err != nil {
   901			return
   902		}
   903		if ns < 0 || 1e9 <= ns {
   904			rangeErrString = "fractional second"
   905			return
   906		}
   907		// We need nanoseconds, which means scaling by the number
   908		// of missing digits in the format, maximum length 10. If it's
   909		// longer than 10, we won't scale.
   910		scaleDigits := 10 - nbytes
   911		for i := 0; i < scaleDigits; i++ {
   912			ns *= 10
   913		}
   914		return
   915	}
   916	
   917	var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
   918	
   919	// leadingInt consumes the leading [0-9]* from s.
   920	func leadingInt(s string) (x int, rem string, err error) {
   921		i := 0
   922		for ; i < len(s); i++ {
   923			c := s[i]
   924			if c < '0' || c > '9' {
   925				break
   926			}
   927			if x >= (1<<31-10)/10 {
   928				// overflow
   929				return 0, "", errLeadingInt
   930			}
   931			x = x*10 + int(c) - '0'
   932		}
   933		return x, s[i:], nil
   934	}
   935	
   936	var unitMap = map[string]float64{
   937		"ns": float64(Nanosecond),
   938		"us": float64(Microsecond),
   939		"µs": float64(Microsecond), // U+00B5 = micro symbol
   940		"μs": float64(Microsecond), // U+03BC = Greek letter mu
   941		"ms": float64(Millisecond),
   942		"s":  float64(Second),
   943		"m":  float64(Minute),
   944		"h":  float64(Hour),
   945	}
   946	
   947	// ParseDuration parses a duration string.
   948	// A duration string is a possibly signed sequence of
   949	// decimal numbers, each with optional fraction and a unit suffix,
   950	// such as "300ms", "-1.5h" or "2h45m".
   951	// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   952	func ParseDuration(s string) (Duration, error) {
   953		// [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
   954		orig := s
   955		f := float64(0)
   956		neg := false
   957	
   958		// Consume [-+]?
   959		if s != "" {
   960			c := s[0]
   961			if c == '-' || c == '+' {
   962				neg = c == '-'
   963				s = s[1:]
   964			}
   965		}
   966		// Special case: if all that is left is "0", this is zero.
   967		if s == "0" {
   968			return 0, nil
   969		}
   970		if s == "" {
   971			return 0, errors.New("time: invalid duration " + orig)
   972		}
   973		for s != "" {
   974			g := float64(0) // this element of the sequence
   975	
   976			var x int
   977			var err error
   978	
   979			// The next character must be [0-9.]
   980			if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
   981				return 0, errors.New("time: invalid duration " + orig)
   982			}
   983			// Consume [0-9]*
   984			pl := len(s)
   985			x, s, err = leadingInt(s)
   986			if err != nil {
   987				return 0, errors.New("time: invalid duration " + orig)
   988			}
   989			g = float64(x)
   990			pre := pl != len(s) // whether we consumed anything before a period
   991	
   992			// Consume (\.[0-9]*)?
   993			post := false
   994			if s != "" && s[0] == '.' {
   995				s = s[1:]
   996				pl := len(s)
   997				x, s, err = leadingInt(s)
   998				if err != nil {
   999					return 0, errors.New("time: invalid duration " + orig)
  1000				}
  1001				scale := 1
  1002				for n := pl - len(s); n > 0; n-- {
  1003					scale *= 10
  1004				}
  1005				g += float64(x) / float64(scale)
  1006				post = pl != len(s)
  1007			}
  1008			if !pre && !post {
  1009				// no digits (e.g. ".s" or "-.s")
  1010				return 0, errors.New("time: invalid duration " + orig)
  1011			}
  1012	
  1013			// Consume unit.
  1014			i := 0
  1015			for ; i < len(s); i++ {
  1016				c := s[i]
  1017				if c == '.' || ('0' <= c && c <= '9') {
  1018					break
  1019				}
  1020			}
  1021			if i == 0 {
  1022				return 0, errors.New("time: missing unit in duration " + orig)
  1023			}
  1024			u := s[:i]
  1025			s = s[i:]
  1026			unit, ok := unitMap[u]
  1027			if !ok {
  1028				return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
  1029			}
  1030	
  1031			f += g * unit
  1032		}
  1033	
  1034		if neg {
  1035			f = -f
  1036		}
  1037		return Duration(f), nil
  1038	}