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

View as plain text