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