...
Run Format

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

View as plain text