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