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

View as plain text