...

Source file src/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 and time.Parse.
    10	// The reference time used in the layouts is the specific time:
    11	//	Mon Jan 2 15:04:05 MST 2006
    12	// which is Unix time 1136239445. Since MST is GMT-0700,
    13	// the reference time can be thought of as
    14	//	01/02 03:04:05PM '06 -0700
    15	// To define your own format, write down what the reference time would look
    16	// like formatted your way; see the values of constants like ANSIC,
    17	// StampMicro or Kitchen for examples. The model is to demonstrate what the
    18	// reference time looks like so that the Format and Parse methods can apply
    19	// the same transformation to a general time value.
    20	//
    21	// Some valid layouts are invalid time values for time.Parse, due to formats
    22	// such as _ for space padding and Z for zone information.
    23	//
    24	// Within the format string, an underscore _ represents a space that may be
    25	// replaced by a digit if the following number (a day) has two digits; for
    26	// compatibility with fixed-width Unix time formats.
    27	//
    28	// A decimal point followed by one or more zeros represents a fractional
    29	// second, printed to the given number of decimal places. A decimal point
    30	// followed by one or more nines represents a fractional second, printed to
    31	// the given number of decimal places, with trailing zeros removed.
    32	// When parsing (only), the input may contain a fractional second
    33	// field immediately after the seconds field, even if the layout does not
    34	// signify its presence. In that case a decimal point followed by a maximal
    35	// series of digits is parsed as a fractional second.
    36	//
    37	// Numeric time zone offsets format as follows:
    38	//	-0700  ±hhmm
    39	//	-07:00 ±hh:mm
    40	//	-07    ±hh
    41	// Replacing the sign in the format with a Z triggers
    42	// the ISO 8601 behavior of printing Z instead of an
    43	// offset for the UTC zone. Thus:
    44	//	Z0700  Z or ±hhmm
    45	//	Z07:00 Z or ±hh:mm
    46	//	Z07    Z or ±hh
    47	//
    48	// The recognized day of week formats are "Mon" and "Monday".
    49	// The recognized month formats are "Jan" and "January".
    50	//
    51	// The formats 2, _2, and 02 are unpadded, space-padded, and zero-padded
    52	// day of month. The formats __2 and 002 are space-padded and zero-padded
    53	// three-character day of year; there is no unpadded day of year format.
    54	//
    55	// Text in the format string that is not recognized as part of the reference
    56	// time is echoed verbatim during Format and expected to appear verbatim
    57	// in the input to Parse.
    58	//
    59	// The executable example for Time.Format demonstrates the working
    60	// of the layout string in detail and is a good reference.
    61	//
    62	// Note that the RFC822, RFC850, and RFC1123 formats should be applied
    63	// only to local times. Applying them to UTC times will use "UTC" as the
    64	// time zone abbreviation, while strictly speaking those RFCs require the
    65	// use of "GMT" in that case.
    66	// In general RFC1123Z should be used instead of RFC1123 for servers
    67	// that insist on that format, and RFC3339 should be preferred for new protocols.
    68	// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting;
    69	// when used with time.Parse they do not accept all the time formats
    70	// permitted by the RFCs.
    71	// The RFC3339Nano format removes trailing zeros from the seconds field
    72	// and thus may not sort correctly once formatted.
    73	const (
    74		ANSIC       = "Mon Jan _2 15:04:05 2006"
    75		UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    76		RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    77		RFC822      = "02 Jan 06 15:04 MST"
    78		RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
    79		RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    80		RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    81		RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
    82		RFC3339     = "2006-01-02T15:04:05Z07:00"
    83		RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    84		Kitchen     = "3:04PM"
    85		// Handy time stamps.
    86		Stamp      = "Jan _2 15:04:05"
    87		StampMilli = "Jan _2 15:04:05.000"
    88		StampMicro = "Jan _2 15:04:05.000000"
    89		StampNano  = "Jan _2 15:04:05.000000000"
    90	)
    91	
    92	const (
    93		_                        = iota
    94		stdLongMonth             = iota + stdNeedDate  // "January"
    95		stdMonth                                       // "Jan"
    96		stdNumMonth                                    // "1"
    97		stdZeroMonth                                   // "01"
    98		stdLongWeekDay                                 // "Monday"
    99		stdWeekDay                                     // "Mon"
   100		stdDay                                         // "2"
   101		stdUnderDay                                    // "_2"
   102		stdZeroDay                                     // "02"
   103		stdUnderYearDay                                // "__2"
   104		stdZeroYearDay                                 // "002"
   105		stdHour                  = iota + stdNeedClock // "15"
   106		stdHour12                                      // "3"
   107		stdZeroHour12                                  // "03"
   108		stdMinute                                      // "4"
   109		stdZeroMinute                                  // "04"
   110		stdSecond                                      // "5"
   111		stdZeroSecond                                  // "05"
   112		stdLongYear              = iota + stdNeedDate  // "2006"
   113		stdYear                                        // "06"
   114		stdPM                    = iota + stdNeedClock // "PM"
   115		stdpm                                          // "pm"
   116		stdTZ                    = iota                // "MST"
   117		stdISO8601TZ                                   // "Z0700"  // prints Z for UTC
   118		stdISO8601SecondsTZ                            // "Z070000"
   119		stdISO8601ShortTZ                              // "Z07"
   120		stdISO8601ColonTZ                              // "Z07:00" // prints Z for UTC
   121		stdISO8601ColonSecondsTZ                       // "Z07:00:00"
   122		stdNumTZ                                       // "-0700"  // always numeric
   123		stdNumSecondsTz                                // "-070000"
   124		stdNumShortTZ                                  // "-07"    // always numeric
   125		stdNumColonTZ                                  // "-07:00" // always numeric
   126		stdNumColonSecondsTZ                           // "-07:00:00"
   127		stdFracSecond0                                 // ".0", ".00", ... , trailing zeros included
   128		stdFracSecond9                                 // ".9", ".99", ..., trailing zeros omitted
   129	
   130		stdNeedDate  = 1 << 8             // need month, day, year
   131		stdNeedClock = 2 << 8             // need hour, minute, second
   132		stdArgShift  = 16                 // extra argument in high bits, above low stdArgShift
   133		stdMask      = 1<<stdArgShift - 1 // mask out argument
   134	)
   135	
   136	// std0x records the std values for "01", "02", ..., "06".
   137	var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
   138	
   139	// startsWithLowerCase reports whether the string has a lower-case letter at the beginning.
   140	// Its purpose is to prevent matching strings like "Month" when looking for "Mon".
   141	func startsWithLowerCase(str string) bool {
   142		if len(str) == 0 {
   143			return false
   144		}
   145		c := str[0]
   146		return 'a' <= c && c <= 'z'
   147	}
   148	
   149	// nextStdChunk finds the first occurrence of a std string in
   150	// layout and returns the text before, the std string, and the text after.
   151	func nextStdChunk(layout string) (prefix string, std int, suffix string) {
   152		for i := 0; i < len(layout); i++ {
   153			switch c := int(layout[i]); c {
   154			case 'J': // January, Jan
   155				if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
   156					if len(layout) >= i+7 && layout[i:i+7] == "January" {
   157						return layout[0:i], stdLongMonth, layout[i+7:]
   158					}
   159					if !startsWithLowerCase(layout[i+3:]) {
   160						return layout[0:i], stdMonth, layout[i+3:]
   161					}
   162				}
   163	
   164			case 'M': // Monday, Mon, MST
   165				if len(layout) >= i+3 {
   166					if layout[i:i+3] == "Mon" {
   167						if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
   168							return layout[0:i], stdLongWeekDay, layout[i+6:]
   169						}
   170						if !startsWithLowerCase(layout[i+3:]) {
   171							return layout[0:i], stdWeekDay, layout[i+3:]
   172						}
   173					}
   174					if layout[i:i+3] == "MST" {
   175						return layout[0:i], stdTZ, layout[i+3:]
   176					}
   177				}
   178	
   179			case '0': // 01, 02, 03, 04, 05, 06, 002
   180				if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
   181					return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
   182				}
   183				if len(layout) >= i+3 && layout[i+1] == '0' && layout[i+2] == '2' {
   184					return layout[0:i], stdZeroYearDay, layout[i+3:]
   185				}
   186	
   187			case '1': // 15, 1
   188				if len(layout) >= i+2 && layout[i+1] == '5' {
   189					return layout[0:i], stdHour, layout[i+2:]
   190				}
   191				return layout[0:i], stdNumMonth, layout[i+1:]
   192	
   193			case '2': // 2006, 2
   194				if len(layout) >= i+4 && layout[i:i+4] == "2006" {
   195					return layout[0:i], stdLongYear, layout[i+4:]
   196				}
   197				return layout[0:i], stdDay, layout[i+1:]
   198	
   199			case '_': // _2, _2006, __2
   200				if len(layout) >= i+2 && layout[i+1] == '2' {
   201					//_2006 is really a literal _, followed by stdLongYear
   202					if len(layout) >= i+5 && layout[i+1:i+5] == "2006" {
   203						return layout[0 : i+1], stdLongYear, layout[i+5:]
   204					}
   205					return layout[0:i], stdUnderDay, layout[i+2:]
   206				}
   207				if len(layout) >= i+3 && layout[i+1] == '_' && layout[i+2] == '2' {
   208					return layout[0:i], stdUnderYearDay, layout[i+3:]
   209				}
   210	
   211			case '3':
   212				return layout[0:i], stdHour12, layout[i+1:]
   213	
   214			case '4':
   215				return layout[0:i], stdMinute, layout[i+1:]
   216	
   217			case '5':
   218				return layout[0:i], stdSecond, layout[i+1:]
   219	
   220			case 'P': // PM
   221				if len(layout) >= i+2 && layout[i+1] == 'M' {
   222					return layout[0:i], stdPM, layout[i+2:]
   223				}
   224	
   225			case 'p': // pm
   226				if len(layout) >= i+2 && layout[i+1] == 'm' {
   227					return layout[0:i], stdpm, layout[i+2:]
   228				}
   229	
   230			case '-': // -070000, -07:00:00, -0700, -07:00, -07
   231				if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
   232					return layout[0:i], stdNumSecondsTz, layout[i+7:]
   233				}
   234				if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
   235					return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
   236				}
   237				if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
   238					return layout[0:i], stdNumTZ, layout[i+5:]
   239				}
   240				if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
   241					return layout[0:i], stdNumColonTZ, layout[i+6:]
   242				}
   243				if len(layout) >= i+3 && layout[i:i+3] == "-07" {
   244					return layout[0:i], stdNumShortTZ, layout[i+3:]
   245				}
   246	
   247			case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
   248				if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
   249					return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
   250				}
   251				if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
   252					return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
   253				}
   254				if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
   255					return layout[0:i], stdISO8601TZ, layout[i+5:]
   256				}
   257				if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
   258					return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
   259				}
   260				if len(layout) >= i+3 && layout[i:i+3] == "Z07" {
   261					return layout[0:i], stdISO8601ShortTZ, layout[i+3:]
   262				}
   263	
   264			case '.': // .000 or .999 - repeated digits for fractional seconds.
   265				if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
   266					ch := layout[i+1]
   267					j := i + 1
   268					for j < len(layout) && layout[j] == ch {
   269						j++
   270					}
   271					// String of digits must end here - only fractional second is all digits.
   272					if !isDigit(layout, j) {
   273						std := stdFracSecond0
   274						if layout[i+1] == '9' {
   275							std = stdFracSecond9
   276						}
   277						std |= (j - (i + 1)) << stdArgShift
   278						return layout[0:i], std, layout[j:]
   279					}
   280				}
   281			}
   282		}
   283		return layout, 0, ""
   284	}
   285	
   286	var longDayNames = []string{
   287		"Sunday",
   288		"Monday",
   289		"Tuesday",
   290		"Wednesday",
   291		"Thursday",
   292		"Friday",
   293		"Saturday",
   294	}
   295	
   296	var shortDayNames = []string{
   297		"Sun",
   298		"Mon",
   299		"Tue",
   300		"Wed",
   301		"Thu",
   302		"Fri",
   303		"Sat",
   304	}
   305	
   306	var shortMonthNames = []string{
   307		"Jan",
   308		"Feb",
   309		"Mar",
   310		"Apr",
   311		"May",
   312		"Jun",
   313		"Jul",
   314		"Aug",
   315		"Sep",
   316		"Oct",
   317		"Nov",
   318		"Dec",
   319	}
   320	
   321	var longMonthNames = []string{
   322		"January",
   323		"February",
   324		"March",
   325		"April",
   326		"May",
   327		"June",
   328		"July",
   329		"August",
   330		"September",
   331		"October",
   332		"November",
   333		"December",
   334	}
   335	
   336	// match reports whether s1 and s2 match ignoring case.
   337	// It is assumed s1 and s2 are the same length.
   338	func match(s1, s2 string) bool {
   339		for i := 0; i < len(s1); i++ {
   340			c1 := s1[i]
   341			c2 := s2[i]
   342			if c1 != c2 {
   343				// Switch to lower-case; 'a'-'A' is known to be a single bit.
   344				c1 |= 'a' - 'A'
   345				c2 |= 'a' - 'A'
   346				if c1 != c2 || c1 < 'a' || c1 > 'z' {
   347					return false
   348				}
   349			}
   350		}
   351		return true
   352	}
   353	
   354	func lookup(tab []string, val string) (int, string, error) {
   355		for i, v := range tab {
   356			if len(val) >= len(v) && match(val[0:len(v)], v) {
   357				return i, val[len(v):], nil
   358			}
   359		}
   360		return -1, val, errBad
   361	}
   362	
   363	// appendInt appends the decimal form of x to b and returns the result.
   364	// If the decimal form (excluding sign) is shorter than width, the result is padded with leading 0's.
   365	// Duplicates functionality in strconv, but avoids dependency.
   366	func appendInt(b []byte, x int, width int) []byte {
   367		u := uint(x)
   368		if x < 0 {
   369			b = append(b, '-')
   370			u = uint(-x)
   371		}
   372	
   373		// Assemble decimal in reverse order.
   374		var buf [20]byte
   375		i := len(buf)
   376		for u >= 10 {
   377			i--
   378			q := u / 10
   379			buf[i] = byte('0' + u - q*10)
   380			u = q
   381		}
   382		i--
   383		buf[i] = byte('0' + u)
   384	
   385		// Add 0-padding.
   386		for w := len(buf) - i; w < width; w++ {
   387			b = append(b, '0')
   388		}
   389	
   390		return append(b, buf[i:]...)
   391	}
   392	
   393	// Never printed, just needs to be non-nil for return by atoi.
   394	var atoiError = errors.New("time: invalid number")
   395	
   396	// Duplicates functionality in strconv, but avoids dependency.
   397	func atoi(s string) (x int, err error) {
   398		neg := false
   399		if s != "" && (s[0] == '-' || s[0] == '+') {
   400			neg = s[0] == '-'
   401			s = s[1:]
   402		}
   403		q, rem, err := leadingInt(s)
   404		x = int(q)
   405		if err != nil || rem != "" {
   406			return 0, atoiError
   407		}
   408		if neg {
   409			x = -x
   410		}
   411		return x, nil
   412	}
   413	
   414	// formatNano appends a fractional second, as nanoseconds, to b
   415	// and returns the result.
   416	func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
   417		u := nanosec
   418		var buf [9]byte
   419		for start := len(buf); start > 0; {
   420			start--
   421			buf[start] = byte(u%10 + '0')
   422			u /= 10
   423		}
   424	
   425		if n > 9 {
   426			n = 9
   427		}
   428		if trim {
   429			for n > 0 && buf[n-1] == '0' {
   430				n--
   431			}
   432			if n == 0 {
   433				return b
   434			}
   435		}
   436		b = append(b, '.')
   437		return append(b, buf[:n]...)
   438	}
   439	
   440	// String returns the time formatted using the format string
   441	//	"2006-01-02 15:04:05.999999999 -0700 MST"
   442	//
   443	// If the time has a monotonic clock reading, the returned string
   444	// includes a final field "m=±<value>", where value is the monotonic
   445	// clock reading formatted as a decimal number of seconds.
   446	//
   447	// The returned string is meant for debugging; for a stable serialized
   448	// representation, use t.MarshalText, t.MarshalBinary, or t.Format
   449	// with an explicit format string.
   450	func (t Time) String() string {
   451		s := t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
   452	
   453		// Format monotonic clock reading as m=±ddd.nnnnnnnnn.
   454		if t.wall&hasMonotonic != 0 {
   455			m2 := uint64(t.ext)
   456			sign := byte('+')
   457			if t.ext < 0 {
   458				sign = '-'
   459				m2 = -m2
   460			}
   461			m1, m2 := m2/1e9, m2%1e9
   462			m0, m1 := m1/1e9, m1%1e9
   463			var buf []byte
   464			buf = append(buf, " m="...)
   465			buf = append(buf, sign)
   466			wid := 0
   467			if m0 != 0 {
   468				buf = appendInt(buf, int(m0), 0)
   469				wid = 9
   470			}
   471			buf = appendInt(buf, int(m1), wid)
   472			buf = append(buf, '.')
   473			buf = appendInt(buf, int(m2), 9)
   474			s += string(buf)
   475		}
   476		return s
   477	}
   478	
   479	// Format returns a textual representation of the time value formatted
   480	// according to layout, which defines the format by showing how the reference
   481	// time, defined to be
   482	//	Mon Jan 2 15:04:05 -0700 MST 2006
   483	// would be displayed if it were the value; it serves as an example of the
   484	// desired output. The same display rules will then be applied to the time
   485	// value.
   486	//
   487	// A fractional second is represented by adding a period and zeros
   488	// to the end of the seconds section of layout string, as in "15:04:05.000"
   489	// to format a time stamp with millisecond precision.
   490	//
   491	// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
   492	// and convenient representations of the reference time. For more information
   493	// about the formats and the definition of the reference time, see the
   494	// documentation for ANSIC and the other constants defined by this package.
   495	func (t Time) Format(layout string) string {
   496		const bufSize = 64
   497		var b []byte
   498		max := len(layout) + 10
   499		if max < bufSize {
   500			var buf [bufSize]byte
   501			b = buf[:0]
   502		} else {
   503			b = make([]byte, 0, max)
   504		}
   505		b = t.AppendFormat(b, layout)
   506		return string(b)
   507	}
   508	
   509	// AppendFormat is like Format but appends the textual
   510	// representation to b and returns the extended buffer.
   511	func (t Time) AppendFormat(b []byte, layout string) []byte {
   512		var (
   513			name, offset, abs = t.locabs()
   514	
   515			year  int = -1
   516			month Month
   517			day   int
   518			yday  int
   519			hour  int = -1
   520			min   int
   521			sec   int
   522		)
   523		// Each iteration generates one std value.
   524		for layout != "" {
   525			prefix, std, suffix := nextStdChunk(layout)
   526			if prefix != "" {
   527				b = append(b, prefix...)
   528			}
   529			if std == 0 {
   530				break
   531			}
   532			layout = suffix
   533	
   534			// Compute year, month, day if needed.
   535			if year < 0 && std&stdNeedDate != 0 {
   536				year, month, day, yday = absDate(abs, true)
   537				yday++
   538			}
   539	
   540			// Compute hour, minute, second if needed.
   541			if hour < 0 && std&stdNeedClock != 0 {
   542				hour, min, sec = absClock(abs)
   543			}
   544	
   545			switch std & stdMask {
   546			case stdYear:
   547				y := year
   548				if y < 0 {
   549					y = -y
   550				}
   551				b = appendInt(b, y%100, 2)
   552			case stdLongYear:
   553				b = appendInt(b, year, 4)
   554			case stdMonth:
   555				b = append(b, month.String()[:3]...)
   556			case stdLongMonth:
   557				m := month.String()
   558				b = append(b, m...)
   559			case stdNumMonth:
   560				b = appendInt(b, int(month), 0)
   561			case stdZeroMonth:
   562				b = appendInt(b, int(month), 2)
   563			case stdWeekDay:
   564				b = append(b, absWeekday(abs).String()[:3]...)
   565			case stdLongWeekDay:
   566				s := absWeekday(abs).String()
   567				b = append(b, s...)
   568			case stdDay:
   569				b = appendInt(b, day, 0)
   570			case stdUnderDay:
   571				if day < 10 {
   572					b = append(b, ' ')
   573				}
   574				b = appendInt(b, day, 0)
   575			case stdZeroDay:
   576				b = appendInt(b, day, 2)
   577			case stdUnderYearDay:
   578				if yday < 100 {
   579					b = append(b, ' ')
   580					if yday < 10 {
   581						b = append(b, ' ')
   582					}
   583				}
   584				b = appendInt(b, yday, 0)
   585			case stdZeroYearDay:
   586				b = appendInt(b, yday, 3)
   587			case stdHour:
   588				b = appendInt(b, hour, 2)
   589			case stdHour12:
   590				// Noon is 12PM, midnight is 12AM.
   591				hr := hour % 12
   592				if hr == 0 {
   593					hr = 12
   594				}
   595				b = appendInt(b, hr, 0)
   596			case stdZeroHour12:
   597				// Noon is 12PM, midnight is 12AM.
   598				hr := hour % 12
   599				if hr == 0 {
   600					hr = 12
   601				}
   602				b = appendInt(b, hr, 2)
   603			case stdMinute:
   604				b = appendInt(b, min, 0)
   605			case stdZeroMinute:
   606				b = appendInt(b, min, 2)
   607			case stdSecond:
   608				b = appendInt(b, sec, 0)
   609			case stdZeroSecond:
   610				b = appendInt(b, sec, 2)
   611			case stdPM:
   612				if hour >= 12 {
   613					b = append(b, "PM"...)
   614				} else {
   615					b = append(b, "AM"...)
   616				}
   617			case stdpm:
   618				if hour >= 12 {
   619					b = append(b, "pm"...)
   620				} else {
   621					b = append(b, "am"...)
   622				}
   623			case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ:
   624				// Ugly special case. We cheat and take the "Z" variants
   625				// to mean "the time zone as formatted for ISO 8601".
   626				if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) {
   627					b = append(b, 'Z')
   628					break
   629				}
   630				zone := offset / 60 // convert to minutes
   631				absoffset := offset
   632				if zone < 0 {
   633					b = append(b, '-')
   634					zone = -zone
   635					absoffset = -absoffset
   636				} else {
   637					b = append(b, '+')
   638				}
   639				b = appendInt(b, zone/60, 2)
   640				if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
   641					b = append(b, ':')
   642				}
   643				if std != stdNumShortTZ && std != stdISO8601ShortTZ {
   644					b = appendInt(b, zone%60, 2)
   645				}
   646	
   647				// append seconds if appropriate
   648				if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
   649					if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
   650						b = append(b, ':')
   651					}
   652					b = appendInt(b, absoffset%60, 2)
   653				}
   654	
   655			case stdTZ:
   656				if name != "" {
   657					b = append(b, name...)
   658					break
   659				}
   660				// No time zone known for this time, but we must print one.
   661				// Use the -0700 format.
   662				zone := offset / 60 // convert to minutes
   663				if zone < 0 {
   664					b = append(b, '-')
   665					zone = -zone
   666				} else {
   667					b = append(b, '+')
   668				}
   669				b = appendInt(b, zone/60, 2)
   670				b = appendInt(b, zone%60, 2)
   671			case stdFracSecond0, stdFracSecond9:
   672				b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
   673			}
   674		}
   675		return b
   676	}
   677	
   678	var errBad = errors.New("bad value for field") // placeholder not passed to user
   679	
   680	// ParseError describes a problem parsing a time string.
   681	type ParseError struct {
   682		Layout     string
   683		Value      string
   684		LayoutElem string
   685		ValueElem  string
   686		Message    string
   687	}
   688	
   689	func quote(s string) string {
   690		return "\"" + s + "\""
   691	}
   692	
   693	// Error returns the string representation of a ParseError.
   694	func (e *ParseError) Error() string {
   695		if e.Message == "" {
   696			return "parsing time " +
   697				quote(e.Value) + " as " +
   698				quote(e.Layout) + ": cannot parse " +
   699				quote(e.ValueElem) + " as " +
   700				quote(e.LayoutElem)
   701		}
   702		return "parsing time " +
   703			quote(e.Value) + e.Message
   704	}
   705	
   706	// isDigit reports whether s[i] is in range and is a decimal digit.
   707	func isDigit(s string, i int) bool {
   708		if len(s) <= i {
   709			return false
   710		}
   711		c := s[i]
   712		return '0' <= c && c <= '9'
   713	}
   714	
   715	// getnum parses s[0:1] or s[0:2] (fixed forces s[0:2])
   716	// as a decimal integer and returns the integer and the
   717	// remainder of the string.
   718	func getnum(s string, fixed bool) (int, string, error) {
   719		if !isDigit(s, 0) {
   720			return 0, s, errBad
   721		}
   722		if !isDigit(s, 1) {
   723			if fixed {
   724				return 0, s, errBad
   725			}
   726			return int(s[0] - '0'), s[1:], nil
   727		}
   728		return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
   729	}
   730	
   731	// getnum3 parses s[0:1], s[0:2], or s[0:3] (fixed forces s[0:3])
   732	// as a decimal integer and returns the integer and the remainder
   733	// of the string.
   734	func getnum3(s string, fixed bool) (int, string, error) {
   735		var n, i int
   736		for i = 0; i < 3 && isDigit(s, i); i++ {
   737			n = n*10 + int(s[i]-'0')
   738		}
   739		if i == 0 || fixed && i != 3 {
   740			return 0, s, errBad
   741		}
   742		return n, s[i:], nil
   743	}
   744	
   745	func cutspace(s string) string {
   746		for len(s) > 0 && s[0] == ' ' {
   747			s = s[1:]
   748		}
   749		return s
   750	}
   751	
   752	// skip removes the given prefix from value,
   753	// treating runs of space characters as equivalent.
   754	func skip(value, prefix string) (string, error) {
   755		for len(prefix) > 0 {
   756			if prefix[0] == ' ' {
   757				if len(value) > 0 && value[0] != ' ' {
   758					return value, errBad
   759				}
   760				prefix = cutspace(prefix)
   761				value = cutspace(value)
   762				continue
   763			}
   764			if len(value) == 0 || value[0] != prefix[0] {
   765				return value, errBad
   766			}
   767			prefix = prefix[1:]
   768			value = value[1:]
   769		}
   770		return value, nil
   771	}
   772	
   773	// Parse parses a formatted string and returns the time value it represents.
   774	// The layout defines the format by showing how the reference time,
   775	// defined to be
   776	//	Mon Jan 2 15:04:05 -0700 MST 2006
   777	// would be interpreted if it were the value; it serves as an example of
   778	// the input format. The same interpretation will then be made to the
   779	// input string.
   780	//
   781	// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
   782	// and convenient representations of the reference time. For more information
   783	// about the formats and the definition of the reference time, see the
   784	// documentation for ANSIC and the other constants defined by this package.
   785	// Also, the executable example for Time.Format demonstrates the working
   786	// of the layout string in detail and is a good reference.
   787	//
   788	// Elements omitted from the value are assumed to be zero or, when
   789	// zero is impossible, one, so parsing "3:04pm" returns the time
   790	// corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
   791	// 0, this time is before the zero Time).
   792	// Years must be in the range 0000..9999. The day of the week is checked
   793	// for syntax but it is otherwise ignored.
   794	//
   795	// In the absence of a time zone indicator, Parse returns a time in UTC.
   796	//
   797	// When parsing a time with a zone offset like -0700, if the offset corresponds
   798	// to a time zone used by the current location (Local), then Parse uses that
   799	// location and zone in the returned time. Otherwise it records the time as
   800	// being in a fabricated location with time fixed at the given zone offset.
   801	//
   802	// When parsing a time with a zone abbreviation like MST, if the zone abbreviation
   803	// has a defined offset in the current location, then that offset is used.
   804	// The zone abbreviation "UTC" is recognized as UTC regardless of location.
   805	// If the zone abbreviation is unknown, Parse records the time as being
   806	// in a fabricated location with the given zone abbreviation and a zero offset.
   807	// This choice means that such a time can be parsed and reformatted with the
   808	// same layout losslessly, but the exact instant used in the representation will
   809	// differ by the actual zone offset. To avoid such problems, prefer time layouts
   810	// that use a numeric zone offset, or use ParseInLocation.
   811	func Parse(layout, value string) (Time, error) {
   812		return parse(layout, value, UTC, Local)
   813	}
   814	
   815	// ParseInLocation is like Parse but differs in two important ways.
   816	// First, in the absence of time zone information, Parse interprets a time as UTC;
   817	// ParseInLocation interprets the time as in the given location.
   818	// Second, when given a zone offset or abbreviation, Parse tries to match it
   819	// against the Local location; ParseInLocation uses the given location.
   820	func ParseInLocation(layout, value string, loc *Location) (Time, error) {
   821		return parse(layout, value, loc, loc)
   822	}
   823	
   824	func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
   825		alayout, avalue := layout, value
   826		rangeErrString := "" // set if a value is out of range
   827		amSet := false       // do we need to subtract 12 from the hour for midnight?
   828		pmSet := false       // do we need to add 12 to the hour?
   829	
   830		// Time being constructed.
   831		var (
   832			year       int
   833			month      int = -1
   834			day        int = -1
   835			yday       int = -1
   836			hour       int
   837			min        int
   838			sec        int
   839			nsec       int
   840			z          *Location
   841			zoneOffset int = -1
   842			zoneName   string
   843		)
   844	
   845		// Each iteration processes one std value.
   846		for {
   847			var err error
   848			prefix, std, suffix := nextStdChunk(layout)
   849			stdstr := layout[len(prefix) : len(layout)-len(suffix)]
   850			value, err = skip(value, prefix)
   851			if err != nil {
   852				return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
   853			}
   854			if std == 0 {
   855				if len(value) != 0 {
   856					return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
   857				}
   858				break
   859			}
   860			layout = suffix
   861			var p string
   862			switch std & stdMask {
   863			case stdYear:
   864				if len(value) < 2 {
   865					err = errBad
   866					break
   867				}
   868				hold := value
   869				p, value = value[0:2], value[2:]
   870				year, err = atoi(p)
   871				if err != nil {
   872					value = hold
   873				} else if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
   874					year += 1900
   875				} else {
   876					year += 2000
   877				}
   878			case stdLongYear:
   879				if len(value) < 4 || !isDigit(value, 0) {
   880					err = errBad
   881					break
   882				}
   883				p, value = value[0:4], value[4:]
   884				year, err = atoi(p)
   885			case stdMonth:
   886				month, value, err = lookup(shortMonthNames, value)
   887				month++
   888			case stdLongMonth:
   889				month, value, err = lookup(longMonthNames, value)
   890				month++
   891			case stdNumMonth, stdZeroMonth:
   892				month, value, err = getnum(value, std == stdZeroMonth)
   893				if err == nil && (month <= 0 || 12 < month) {
   894					rangeErrString = "month"
   895				}
   896			case stdWeekDay:
   897				// Ignore weekday except for error checking.
   898				_, value, err = lookup(shortDayNames, value)
   899			case stdLongWeekDay:
   900				_, value, err = lookup(longDayNames, value)
   901			case stdDay, stdUnderDay, stdZeroDay:
   902				if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
   903					value = value[1:]
   904				}
   905				day, value, err = getnum(value, std == stdZeroDay)
   906				// Note that we allow any one- or two-digit day here.
   907				// The month, day, year combination is validated after we've completed parsing.
   908			case stdUnderYearDay, stdZeroYearDay:
   909				for i := 0; i < 2; i++ {
   910					if std == stdUnderYearDay && len(value) > 0 && value[0] == ' ' {
   911						value = value[1:]
   912					}
   913				}
   914				yday, value, err = getnum3(value, std == stdZeroYearDay)
   915				// Note that we allow any one-, two-, or three-digit year-day here.
   916				// The year-day, year combination is validated after we've completed parsing.
   917			case stdHour:
   918				hour, value, err = getnum(value, false)
   919				if hour < 0 || 24 <= hour {
   920					rangeErrString = "hour"
   921				}
   922			case stdHour12, stdZeroHour12:
   923				hour, value, err = getnum(value, std == stdZeroHour12)
   924				if hour < 0 || 12 < hour {
   925					rangeErrString = "hour"
   926				}
   927			case stdMinute, stdZeroMinute:
   928				min, value, err = getnum(value, std == stdZeroMinute)
   929				if min < 0 || 60 <= min {
   930					rangeErrString = "minute"
   931				}
   932			case stdSecond, stdZeroSecond:
   933				sec, value, err = getnum(value, std == stdZeroSecond)
   934				if sec < 0 || 60 <= sec {
   935					rangeErrString = "second"
   936					break
   937				}
   938				// Special case: do we have a fractional second but no
   939				// fractional second in the format?
   940				if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
   941					_, std, _ = nextStdChunk(layout)
   942					std &= stdMask
   943					if std == stdFracSecond0 || std == stdFracSecond9 {
   944						// Fractional second in the layout; proceed normally
   945						break
   946					}
   947					// No fractional second in the layout but we have one in the input.
   948					n := 2
   949					for ; n < len(value) && isDigit(value, n); n++ {
   950					}
   951					nsec, rangeErrString, err = parseNanoseconds(value, n)
   952					value = value[n:]
   953				}
   954			case stdPM:
   955				if len(value) < 2 {
   956					err = errBad
   957					break
   958				}
   959				p, value = value[0:2], value[2:]
   960				switch p {
   961				case "PM":
   962					pmSet = true
   963				case "AM":
   964					amSet = true
   965				default:
   966					err = errBad
   967				}
   968			case stdpm:
   969				if len(value) < 2 {
   970					err = errBad
   971					break
   972				}
   973				p, value = value[0:2], value[2:]
   974				switch p {
   975				case "pm":
   976					pmSet = true
   977				case "am":
   978					amSet = true
   979				default:
   980					err = errBad
   981				}
   982			case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
   983				if (std == stdISO8601TZ || std == stdISO8601ShortTZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
   984					value = value[1:]
   985					z = UTC
   986					break
   987				}
   988				var sign, hour, min, seconds string
   989				if std == stdISO8601ColonTZ || std == stdNumColonTZ {
   990					if len(value) < 6 {
   991						err = errBad
   992						break
   993					}
   994					if value[3] != ':' {
   995						err = errBad
   996						break
   997					}
   998					sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
   999				} else if std == stdNumShortTZ || std == stdISO8601ShortTZ {
  1000					if len(value) < 3 {
  1001						err = errBad
  1002						break
  1003					}
  1004					sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
  1005				} else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
  1006					if len(value) < 9 {
  1007						err = errBad
  1008						break
  1009					}
  1010					if value[3] != ':' || value[6] != ':' {
  1011						err = errBad
  1012						break
  1013					}
  1014					sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
  1015				} else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
  1016					if len(value) < 7 {
  1017						err = errBad
  1018						break
  1019					}
  1020					sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
  1021				} else {
  1022					if len(value) < 5 {
  1023						err = errBad
  1024						break
  1025					}
  1026					sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
  1027				}
  1028				var hr, mm, ss int
  1029				hr, err = atoi(hour)
  1030				if err == nil {
  1031					mm, err = atoi(min)
  1032				}
  1033				if err == nil {
  1034					ss, err = atoi(seconds)
  1035				}
  1036				zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
  1037				switch sign[0] {
  1038				case '+':
  1039				case '-':
  1040					zoneOffset = -zoneOffset
  1041				default:
  1042					err = errBad
  1043				}
  1044			case stdTZ:
  1045				// Does it look like a time zone?
  1046				if len(value) >= 3 && value[0:3] == "UTC" {
  1047					z = UTC
  1048					value = value[3:]
  1049					break
  1050				}
  1051				n, ok := parseTimeZone(value)
  1052				if !ok {
  1053					err = errBad
  1054					break
  1055				}
  1056				zoneName, value = value[:n], value[n:]
  1057	
  1058			case stdFracSecond0:
  1059				// stdFracSecond0 requires the exact number of digits as specified in
  1060				// the layout.
  1061				ndigit := 1 + (std >> stdArgShift)
  1062				if len(value) < ndigit {
  1063					err = errBad
  1064					break
  1065				}
  1066				nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
  1067				value = value[ndigit:]
  1068	
  1069			case stdFracSecond9:
  1070				if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
  1071					// Fractional second omitted.
  1072					break
  1073				}
  1074				// Take any number of digits, even more than asked for,
  1075				// because it is what the stdSecond case would do.
  1076				i := 0
  1077				for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
  1078					i++
  1079				}
  1080				nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
  1081				value = value[1+i:]
  1082			}
  1083			if rangeErrString != "" {
  1084				return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
  1085			}
  1086			if err != nil {
  1087				return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
  1088			}
  1089		}
  1090		if pmSet && hour < 12 {
  1091			hour += 12
  1092		} else if amSet && hour == 12 {
  1093			hour = 0
  1094		}
  1095	
  1096		// Convert yday to day, month.
  1097		if yday >= 0 {
  1098			var d int
  1099			var m int
  1100			if isLeap(year) {
  1101				if yday == 31+29 {
  1102					m = int(February)
  1103					d = 29
  1104				} else if yday > 31+29 {
  1105					yday--
  1106				}
  1107			}
  1108			if yday < 1 || yday > 365 {
  1109				return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year out of range"}
  1110			}
  1111			if m == 0 {
  1112				m = yday/31 + 1
  1113				if int(daysBefore[m]) < yday {
  1114					m++
  1115				}
  1116				d = yday - int(daysBefore[m-1])
  1117			}
  1118			// If month, day already seen, yday's m, d must match.
  1119			// Otherwise, set them from m, d.
  1120			if month >= 0 && month != m {
  1121				return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year does not match month"}
  1122			}
  1123			month = m
  1124			if day >= 0 && day != d {
  1125				return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year does not match day"}
  1126			}
  1127			day = d
  1128		} else {
  1129			if month < 0 {
  1130				month = int(January)
  1131			}
  1132			if day < 0 {
  1133				day = 1
  1134			}
  1135		}
  1136	
  1137		// Validate the day of the month.
  1138		if day < 1 || day > daysIn(Month(month), year) {
  1139			return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"}
  1140		}
  1141	
  1142		if z != nil {
  1143			return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
  1144		}
  1145	
  1146		if zoneOffset != -1 {
  1147			t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
  1148			t.addSec(-int64(zoneOffset))
  1149	
  1150			// Look for local zone with the given offset.
  1151			// If that zone was in effect at the given time, use it.
  1152			name, offset, _, _ := local.lookup(t.unixSec())
  1153			if offset == zoneOffset && (zoneName == "" || name == zoneName) {
  1154				t.setLoc(local)
  1155				return t, nil
  1156			}
  1157	
  1158			// Otherwise create fake zone to record offset.
  1159			t.setLoc(FixedZone(zoneName, zoneOffset))
  1160			return t, nil
  1161		}
  1162	
  1163		if zoneName != "" {
  1164			t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
  1165			// Look for local zone with the given offset.
  1166			// If that zone was in effect at the given time, use it.
  1167			offset, ok := local.lookupName(zoneName, t.unixSec())
  1168			if ok {
  1169				t.addSec(-int64(offset))
  1170				t.setLoc(local)
  1171				return t, nil
  1172			}
  1173	
  1174			// Otherwise, create fake zone with unknown offset.
  1175			if len(zoneName) > 3 && zoneName[:3] == "GMT" {
  1176				offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
  1177				offset *= 3600
  1178			}
  1179			t.setLoc(FixedZone(zoneName, offset))
  1180			return t, nil
  1181		}
  1182	
  1183		// Otherwise, fall back to default.
  1184		return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
  1185	}
  1186	
  1187	// parseTimeZone parses a time zone string and returns its length. Time zones
  1188	// are human-generated and unpredictable. We can't do precise error checking.
  1189	// On the other hand, for a correct parse there must be a time zone at the
  1190	// beginning of the string, so it's almost always true that there's one
  1191	// there. We look at the beginning of the string for a run of upper-case letters.
  1192	// If there are more than 5, it's an error.
  1193	// If there are 4 or 5 and the last is a T, it's a time zone.
  1194	// If there are 3, it's a time zone.
  1195	// Otherwise, other than special cases, it's not a time zone.
  1196	// GMT is special because it can have an hour offset.
  1197	func parseTimeZone(value string) (length int, ok bool) {
  1198		if len(value) < 3 {
  1199			return 0, false
  1200		}
  1201		// Special case 1: ChST and MeST are the only zones with a lower-case letter.
  1202		if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
  1203			return 4, true
  1204		}
  1205		// Special case 2: GMT may have an hour offset; treat it specially.
  1206		if value[:3] == "GMT" {
  1207			length = parseGMT(value)
  1208			return length, true
  1209		}
  1210		// Special Case 3: Some time zones are not named, but have +/-00 format
  1211		if value[0] == '+' || value[0] == '-' {
  1212			length = parseSignedOffset(value)
  1213			ok := length > 0 // parseSignedOffset returns 0 in case of bad input
  1214			return length, ok
  1215		}
  1216		// How many upper-case letters are there? Need at least three, at most five.
  1217		var nUpper int
  1218		for nUpper = 0; nUpper < 6; nUpper++ {
  1219			if nUpper >= len(value) {
  1220				break
  1221			}
  1222			if c := value[nUpper]; c < 'A' || 'Z' < c {
  1223				break
  1224			}
  1225		}
  1226		switch nUpper {
  1227		case 0, 1, 2, 6:
  1228			return 0, false
  1229		case 5: // Must end in T to match.
  1230			if value[4] == 'T' {
  1231				return 5, true
  1232			}
  1233		case 4:
  1234			// Must end in T, except one special case.
  1235			if value[3] == 'T' || value[:4] == "WITA" {
  1236				return 4, true
  1237			}
  1238		case 3:
  1239			return 3, true
  1240		}
  1241		return 0, false
  1242	}
  1243	
  1244	// parseGMT parses a GMT time zone. The input string is known to start "GMT".
  1245	// The function checks whether that is followed by a sign and a number in the
  1246	// range -23 through +23 excluding zero.
  1247	func parseGMT(value string) int {
  1248		value = value[3:]
  1249		if len(value) == 0 {
  1250			return 3
  1251		}
  1252	
  1253		return 3 + parseSignedOffset(value)
  1254	}
  1255	
  1256	// parseSignedOffset parses a signed timezone offset (e.g. "+03" or "-04").
  1257	// The function checks for a signed number in the range -23 through +23 excluding zero.
  1258	// Returns length of the found offset string or 0 otherwise
  1259	func parseSignedOffset(value string) int {
  1260		sign := value[0]
  1261		if sign != '-' && sign != '+' {
  1262			return 0
  1263		}
  1264		x, rem, err := leadingInt(value[1:])
  1265	
  1266		// fail if nothing consumed by leadingInt
  1267		if err != nil || value[1:] == rem {
  1268			return 0
  1269		}
  1270		if sign == '-' {
  1271			x = -x
  1272		}
  1273		if x < -23 || 23 < x {
  1274			return 0
  1275		}
  1276		return len(value) - len(rem)
  1277	}
  1278	
  1279	func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
  1280		if value[0] != '.' {
  1281			err = errBad
  1282			return
  1283		}
  1284		if ns, err = atoi(value[1:nbytes]); err != nil {
  1285			return
  1286		}
  1287		if ns < 0 || 1e9 <= ns {
  1288			rangeErrString = "fractional second"
  1289			return
  1290		}
  1291		// We need nanoseconds, which means scaling by the number
  1292		// of missing digits in the format, maximum length 10. If it's
  1293		// longer than 10, we won't scale.
  1294		scaleDigits := 10 - nbytes
  1295		for i := 0; i < scaleDigits; i++ {
  1296			ns *= 10
  1297		}
  1298		return
  1299	}
  1300	
  1301	var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
  1302	
  1303	// leadingInt consumes the leading [0-9]* from s.
  1304	func leadingInt(s string) (x int64, rem string, err error) {
  1305		i := 0
  1306		for ; i < len(s); i++ {
  1307			c := s[i]
  1308			if c < '0' || c > '9' {
  1309				break
  1310			}
  1311			if x > (1<<63-1)/10 {
  1312				// overflow
  1313				return 0, "", errLeadingInt
  1314			}
  1315			x = x*10 + int64(c) - '0'
  1316			if x < 0 {
  1317				// overflow
  1318				return 0, "", errLeadingInt
  1319			}
  1320		}
  1321		return x, s[i:], nil
  1322	}
  1323	
  1324	// leadingFraction consumes the leading [0-9]* from s.
  1325	// It is used only for fractions, so does not return an error on overflow,
  1326	// it just stops accumulating precision.
  1327	func leadingFraction(s string) (x int64, scale float64, rem string) {
  1328		i := 0
  1329		scale = 1
  1330		overflow := false
  1331		for ; i < len(s); i++ {
  1332			c := s[i]
  1333			if c < '0' || c > '9' {
  1334				break
  1335			}
  1336			if overflow {
  1337				continue
  1338			}
  1339			if x > (1<<63-1)/10 {
  1340				// It's possible for overflow to give a positive number, so take care.
  1341				overflow = true
  1342				continue
  1343			}
  1344			y := x*10 + int64(c) - '0'
  1345			if y < 0 {
  1346				overflow = true
  1347				continue
  1348			}
  1349			x = y
  1350			scale *= 10
  1351		}
  1352		return x, scale, s[i:]
  1353	}
  1354	
  1355	var unitMap = map[string]int64{
  1356		"ns": int64(Nanosecond),
  1357		"us": int64(Microsecond),
  1358		"µs": int64(Microsecond), // U+00B5 = micro symbol
  1359		"μs": int64(Microsecond), // U+03BC = Greek letter mu
  1360		"ms": int64(Millisecond),
  1361		"s":  int64(Second),
  1362		"m":  int64(Minute),
  1363		"h":  int64(Hour),
  1364	}
  1365	
  1366	// ParseDuration parses a duration string.
  1367	// A duration string is a possibly signed sequence of
  1368	// decimal numbers, each with optional fraction and a unit suffix,
  1369	// such as "300ms", "-1.5h" or "2h45m".
  1370	// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
  1371	func ParseDuration(s string) (Duration, error) {
  1372		// [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
  1373		orig := s
  1374		var d int64
  1375		neg := false
  1376	
  1377		// Consume [-+]?
  1378		if s != "" {
  1379			c := s[0]
  1380			if c == '-' || c == '+' {
  1381				neg = c == '-'
  1382				s = s[1:]
  1383			}
  1384		}
  1385		// Special case: if all that is left is "0", this is zero.
  1386		if s == "0" {
  1387			return 0, nil
  1388		}
  1389		if s == "" {
  1390			return 0, errors.New("time: invalid duration " + orig)
  1391		}
  1392		for s != "" {
  1393			var (
  1394				v, f  int64       // integers before, after decimal point
  1395				scale float64 = 1 // value = v + f/scale
  1396			)
  1397	
  1398			var err error
  1399	
  1400			// The next character must be [0-9.]
  1401			if !(s[0] == '.' || '0' <= s[0] && s[0] <= '9') {
  1402				return 0, errors.New("time: invalid duration " + orig)
  1403			}
  1404			// Consume [0-9]*
  1405			pl := len(s)
  1406			v, s, err = leadingInt(s)
  1407			if err != nil {
  1408				return 0, errors.New("time: invalid duration " + orig)
  1409			}
  1410			pre := pl != len(s) // whether we consumed anything before a period
  1411	
  1412			// Consume (\.[0-9]*)?
  1413			post := false
  1414			if s != "" && s[0] == '.' {
  1415				s = s[1:]
  1416				pl := len(s)
  1417				f, scale, s = leadingFraction(s)
  1418				post = pl != len(s)
  1419			}
  1420			if !pre && !post {
  1421				// no digits (e.g. ".s" or "-.s")
  1422				return 0, errors.New("time: invalid duration " + orig)
  1423			}
  1424	
  1425			// Consume unit.
  1426			i := 0
  1427			for ; i < len(s); i++ {
  1428				c := s[i]
  1429				if c == '.' || '0' <= c && c <= '9' {
  1430					break
  1431				}
  1432			}
  1433			if i == 0 {
  1434				return 0, errors.New("time: missing unit in duration " + orig)
  1435			}
  1436			u := s[:i]
  1437			s = s[i:]
  1438			unit, ok := unitMap[u]
  1439			if !ok {
  1440				return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
  1441			}
  1442			if v > (1<<63-1)/unit {
  1443				// overflow
  1444				return 0, errors.New("time: invalid duration " + orig)
  1445			}
  1446			v *= unit
  1447			if f > 0 {
  1448				// float64 is needed to be nanosecond accurate for fractions of hours.
  1449				// v >= 0 && (f*unit/scale) <= 3.6e+12 (ns/h, h is the largest unit)
  1450				v += int64(float64(f) * (float64(unit) / scale))
  1451				if v < 0 {
  1452					// overflow
  1453					return 0, errors.New("time: invalid duration " + orig)
  1454				}
  1455			}
  1456			d += v
  1457			if d < 0 {
  1458				// overflow
  1459				return 0, errors.New("time: invalid duration " + orig)
  1460			}
  1461		}
  1462	
  1463		if neg {
  1464			d = -d
  1465		}
  1466		return Duration(d), nil
  1467	}
  1468	

View as plain text