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