Source file src/pkg/time/format.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package time
6
7 import "errors"
8
9 // These are predefined layouts for use in Time.Format.
10 // The standard time used in the layouts is:
11 // Mon Jan 2 15:04:05 MST 2006
12 // which is Unix time 1136243045. Since MST is GMT-0700,
13 // the standard time can be thought of as
14 // 01/02 03:04:05PM '06 -0700
15 // To define your own format, write down what the standard time would look
16 // like formatted your way; see the values of constants like ANSIC,
17 // StampMicro or Kitchen for examples.
18 //
19 // Within the format string, an underscore _ represents a space that may be
20 // replaced by a digit if the following number (a day) has two digits; for
21 // compatibility with fixed-width Unix time formats.
22 //
23 // A decimal point followed by one or more zeros represents a fractional
24 // second, printed to the given number of decimal places. A decimal point
25 // followed by one or more nines represents a fractional second, printed to
26 // the given number of decimal places, with trailing zeros removed.
27 // When parsing (only), the input may contain a fractional second
28 // field immediately after the seconds field, even if the layout does not
29 // signify its presence. In that case a decimal point followed by a maximal
30 // series of digits is parsed as a fractional second.
31 //
32 // Numeric time zone offsets format as follows:
33 // -0700 ±hhmm
34 // -07:00 ±hh:mm
35 // Replacing the sign in the format with a Z triggers
36 // the ISO 8601 behavior of printing Z instead of an
37 // offset for the UTC zone. Thus:
38 // Z0700 Z or ±hhmm
39 // Z07:00 Z or ±hh:mm
40 const (
41 ANSIC = "Mon Jan _2 15:04:05 2006"
42 UnixDate = "Mon Jan _2 15:04:05 MST 2006"
43 RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
44 RFC822 = "02 Jan 06 15:04 MST"
45 RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
46 RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
47 RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
48 RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
49 RFC3339 = "2006-01-02T15:04:05Z07:00"
50 RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
51 Kitchen = "3:04PM"
52 // Handy time stamps.
53 Stamp = "Jan _2 15:04:05"
54 StampMilli = "Jan _2 15:04:05.000"
55 StampMicro = "Jan _2 15:04:05.000000"
56 StampNano = "Jan _2 15:04:05.000000000"
57 )
58
59 const (
60 stdLongMonth = "January"
61 stdMonth = "Jan"
62 stdNumMonth = "1"
63 stdZeroMonth = "01"
64 stdLongWeekDay = "Monday"
65 stdWeekDay = "Mon"
66 stdDay = "2"
67 stdUnderDay = "_2"
68 stdZeroDay = "02"
69 stdHour = "15"
70 stdHour12 = "3"
71 stdZeroHour12 = "03"
72 stdMinute = "4"
73 stdZeroMinute = "04"
74 stdSecond = "5"
75 stdZeroSecond = "05"
76 stdLongYear = "2006"
77 stdYear = "06"
78 stdPM = "PM"
79 stdpm = "pm"
80 stdTZ = "MST"
81 stdISO8601TZ = "Z0700" // prints Z for UTC
82 stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
83 stdNumTZ = "-0700" // always numeric
84 stdNumShortTZ = "-07" // always numeric
85 stdNumColonTZ = "-07:00" // always numeric
86 )
87
88 // nextStdChunk finds the first occurrence of a std string in
89 // layout and returns the text before, the std string, and the text after.
90 func nextStdChunk(layout string) (prefix, std, suffix string) {
91 for i := 0; i < len(layout); i++ {
92 switch layout[i] {
93 case 'J': // January, Jan
94 if len(layout) >= i+7 && layout[i:i+7] == stdLongMonth {
95 return layout[0:i], stdLongMonth, layout[i+7:]
96 }
97 if len(layout) >= i+3 && layout[i:i+3] == stdMonth {
98 return layout[0:i], stdMonth, layout[i+3:]
99 }
100
101 case 'M': // Monday, Mon, MST
102 if len(layout) >= i+6 && layout[i:i+6] == stdLongWeekDay {
103 return layout[0:i], stdLongWeekDay, layout[i+6:]
104 }
105 if len(layout) >= i+3 {
106 if layout[i:i+3] == stdWeekDay {
107 return layout[0:i], stdWeekDay, layout[i+3:]
108 }
109 if layout[i:i+3] == stdTZ {
110 return layout[0:i], stdTZ, layout[i+3:]
111 }
112 }
113
114 case '0': // 01, 02, 03, 04, 05, 06
115 if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
116 return layout[0:i], layout[i : i+2], layout[i+2:]
117 }
118
119 case '1': // 15, 1
120 if len(layout) >= i+2 && layout[i+1] == '5' {
121 return layout[0:i], stdHour, layout[i+2:]
122 }
123 return layout[0:i], stdNumMonth, layout[i+1:]
124
125 case '2': // 2006, 2
126 if len(layout) >= i+4 && layout[i:i+4] == stdLongYear {
127 return layout[0:i], stdLongYear, layout[i+4:]
128 }
129 return layout[0:i], stdDay, layout[i+1:]
130
131 case '_': // _2
132 if len(layout) >= i+2 && layout[i+1] == '2' {
133 return layout[0:i], stdUnderDay, layout[i+2:]
134 }
135
136 case '3', '4', '5': // 3, 4, 5
137 return layout[0:i], layout[i : i+1], layout[i+1:]
138
139 case 'P': // PM
140 if len(layout) >= i+2 && layout[i+1] == 'M' {
141 return layout[0:i], layout[i : i+2], layout[i+2:]
142 }
143
144 case 'p': // pm
145 if len(layout) >= i+2 && layout[i+1] == 'm' {
146 return layout[0:i], layout[i : i+2], layout[i+2:]
147 }
148
149 case '-': // -0700, -07:00, -07
150 if len(layout) >= i+5 && layout[i:i+5] == stdNumTZ {
151 return layout[0:i], layout[i : i+5], layout[i+5:]
152 }
153 if len(layout) >= i+6 && layout[i:i+6] == stdNumColonTZ {
154 return layout[0:i], layout[i : i+6], layout[i+6:]
155 }
156 if len(layout) >= i+3 && layout[i:i+3] == stdNumShortTZ {
157 return layout[0:i], layout[i : i+3], layout[i+3:]
158 }
159 case 'Z': // Z0700, Z07:00
160 if len(layout) >= i+5 && layout[i:i+5] == stdISO8601TZ {
161 return layout[0:i], layout[i : i+5], layout[i+5:]
162 }
163 if len(layout) >= i+6 && layout[i:i+6] == stdISO8601ColonTZ {
164 return layout[0:i], layout[i : i+6], layout[i+6:]
165 }
166 case '.': // .000 or .999 - repeated digits for fractional seconds.
167 if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
168 ch := layout[i+1]
169 j := i + 1
170 for j < len(layout) && layout[j] == ch {
171 j++
172 }
173 // String of digits must end here - only fractional second is all digits.
174 if !isDigit(layout, j) {
175 return layout[0:i], layout[i:j], layout[j:]
176 }
177 }
178 }
179 }
180 return layout, "", ""
181 }
182
183 var longDayNames = []string{
184 "Sunday",
185 "Monday",
186 "Tuesday",
187 "Wednesday",
188 "Thursday",
189 "Friday",
190 "Saturday",
191 }
192
193 var shortDayNames = []string{
194 "Sun",
195 "Mon",
196 "Tue",
197 "Wed",
198 "Thu",
199 "Fri",
200 "Sat",
201 }
202
203 var shortMonthNames = []string{
204 "---",
205 "Jan",
206 "Feb",
207 "Mar",
208 "Apr",
209 "May",
210 "Jun",
211 "Jul",
212 "Aug",
213 "Sep",
214 "Oct",
215 "Nov",
216 "Dec",
217 }
218
219 var longMonthNames = []string{
220 "---",
221 "January",
222 "February",
223 "March",
224 "April",
225 "May",
226 "June",
227 "July",
228 "August",
229 "September",
230 "October",
231 "November",
232 "December",
233 }
234
235 // match returns true if s1 and s2 match ignoring case.
236 // It is assumed s1 and s2 are the same length.
237 func match(s1, s2 string) bool {
238 for i := 0; i < len(s1); i++ {
239 c1 := s1[i]
240 c2 := s2[i]
241 if c1 != c2 {
242 // Switch to lower-case; 'a'-'A' is known to be a single bit.
243 c1 |= 'a' - 'A'
244 c2 |= 'a' - 'A'
245 if c1 != c2 || c1 < 'a' || c1 > 'z' {
246 return false
247 }
248 }
249 }
250 return true
251 }
252
253 func lookup(tab []string, val string) (int, string, error) {
254 for i, v := range tab {
255 if len(val) >= len(v) && match(val[0:len(v)], v) {
256 return i, val[len(v):], nil
257 }
258 }
259 return -1, val, errBad
260 }
261
262 // Duplicates functionality in strconv, but avoids dependency.
263 func itoa(x int) string {
264 var buf [32]byte
265 n := len(buf)
266 if x == 0 {
267 return "0"
268 }
269 u := uint(x)
270 if x < 0 {
271 u = -u
272 }
273 for u > 0 {
274 n--
275 buf[n] = byte(u%10 + '0')
276 u /= 10
277 }
278 if x < 0 {
279 n--
280 buf[n] = '-'
281 }
282 return string(buf[n:])
283 }
284
285 // Never printed, just needs to be non-nil for return by atoi.
286 var atoiError = errors.New("time: invalid number")
287
288 // Duplicates functionality in strconv, but avoids dependency.
289 func atoi(s string) (x int, err error) {
290 neg := false
291 if s != "" && s[0] == '-' {
292 neg = true
293 s = s[1:]
294 }
295 x, rem, err := leadingInt(s)
296 if err != nil || rem != "" {
297 return 0, atoiError
298 }
299 if neg {
300 x = -x
301 }
302 return x, nil
303 }
304
305 func pad(i int, padding string) string {
306 s := itoa(i)
307 if i < 10 {
308 s = padding + s
309 }
310 return s
311 }
312
313 func zeroPad(i int) string { return pad(i, "0") }
314
315 // formatNano formats a fractional second, as nanoseconds.
316 func formatNano(nanosec, n int, trim bool) string {
317 // User might give us bad data. Make sure it's positive and in range.
318 // They'll get nonsense output but it will have the right format.
319 s := itoa(int(uint(nanosec) % 1e9))
320 // Zero pad left without fmt.
321 if len(s) < 9 {
322 s = "000000000"[:9-len(s)] + s
323 }
324 if n > 9 {
325 n = 9
326 }
327 if trim {
328 for n > 0 && s[n-1] == '0' {
329 n--
330 }
331 if n == 0 {
332 return ""
333 }
334 }
335 return "." + s[:n]
336 }
337
338 // String returns the time formatted using the format string
339 // "2006-01-02 15:04:05.999999999 -0700 MST"
340 func (t Time) String() string {
341 return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
342 }
343
344 type buffer []byte
345
346 func (b *buffer) WriteString(s string) {
347 *b = append(*b, s...)
348 }
349
350 func (b *buffer) String() string {
351 return string([]byte(*b))
352 }
353
354 // Format returns a textual representation of the time value formatted
355 // according to layout. The layout defines the format by showing the
356 // representation of the standard time,
357 // Mon Jan 2 15:04:05 -0700 MST 2006
358 // which is then used to describe the time to be formatted. Predefined
359 // layouts ANSIC, UnixDate, RFC3339 and others describe standard
360 // representations. For more information about the formats and the
361 // definition of the standard time, see the documentation for ANSIC.
362 func (t Time) Format(layout string) string {
363 var (
364 year int = -1
365 month Month
366 day int
367 hour int = -1
368 min int
369 sec int
370 b buffer
371 )
372 // Each iteration generates one std value.
373 for {
374 prefix, std, suffix := nextStdChunk(layout)
375 b.WriteString(prefix)
376 if std == "" {
377 break
378 }
379
380 // Compute year, month, day if needed.
381 if year < 0 {
382 // Jan 01 02 2006
383 if a, z := std[0], std[len(std)-1]; a == 'J' || a == 'j' || z == '1' || z == '2' || z == '6' {
384 year, month, day = t.Date()
385 }
386 }
387
388 // Compute hour, minute, second if needed.
389 if hour < 0 {
390 // 03 04 05 15 pm
391 if z := std[len(std)-1]; z == '3' || z == '4' || z == '5' || z == 'm' || z == 'M' {
392 hour, min, sec = t.Clock()
393 }
394 }
395
396 var p string
397 switch std {
398 case stdYear:
399 p = zeroPad(year % 100)
400 case stdLongYear:
401 // Pad year to at least 4 digits.
402 p = itoa(year)
403 switch {
404 case year <= -1000:
405 // ok
406 case year <= -100:
407 p = p[:1] + "0" + p[1:]
408 case year <= -10:
409 p = p[:1] + "00" + p[1:]
410 case year < 0:
411 p = p[:1] + "000" + p[1:]
412 case year < 10:
413 p = "000" + p
414 case year < 100:
415 p = "00" + p
416 case year < 1000:
417 p = "0" + p
418 }
419 case stdMonth:
420 p = month.String()[:3]
421 case stdLongMonth:
422 p = month.String()
423 case stdNumMonth:
424 p = itoa(int(month))
425 case stdZeroMonth:
426 p = zeroPad(int(month))
427 case stdWeekDay:
428 p = t.Weekday().String()[:3]
429 case stdLongWeekDay:
430 p = t.Weekday().String()
431 case stdDay:
432 p = itoa(day)
433 case stdUnderDay:
434 p = pad(day, " ")
435 case stdZeroDay:
436 p = zeroPad(day)
437 case stdHour:
438 p = zeroPad(hour)
439 case stdHour12:
440 // Noon is 12PM, midnight is 12AM.
441 hr := hour % 12
442 if hr == 0 {
443 hr = 12
444 }
445 p = itoa(hr)
446 case stdZeroHour12:
447 // Noon is 12PM, midnight is 12AM.
448 hr := hour % 12
449 if hr == 0 {
450 hr = 12
451 }
452 p = zeroPad(hr)
453 case stdMinute:
454 p = itoa(min)
455 case stdZeroMinute:
456 p = zeroPad(min)
457 case stdSecond:
458 p = itoa(sec)
459 case stdZeroSecond:
460 p = zeroPad(sec)
461 case stdPM:
462 if hour >= 12 {
463 p = "PM"
464 } else {
465 p = "AM"
466 }
467 case stdpm:
468 if hour >= 12 {
469 p = "pm"
470 } else {
471 p = "am"
472 }
473 case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
474 // Ugly special case. We cheat and take the "Z" variants
475 // to mean "the time zone as formatted for ISO 8601".
476 _, offset := t.Zone()
477 if offset == 0 && std[0] == 'Z' {
478 p = "Z"
479 break
480 }
481 zone := offset / 60 // convert to minutes
482 if zone < 0 {
483 p = "-"
484 zone = -zone
485 } else {
486 p = "+"
487 }
488 p += zeroPad(zone / 60)
489 if std == stdISO8601ColonTZ || std == stdNumColonTZ {
490 p += ":"
491 }
492 p += zeroPad(zone % 60)
493 case stdTZ:
494 name, offset := t.Zone()
495 if name != "" {
496 p = name
497 } else {
498 // No time zone known for this time, but we must print one.
499 // Use the -0700 format.
500 zone := offset / 60 // convert to minutes
501 if zone < 0 {
502 p = "-"
503 zone = -zone
504 } else {
505 p = "+"
506 }
507 p += zeroPad(zone / 60)
508 p += zeroPad(zone % 60)
509 }
510 default:
511 if len(std) >= 2 && (std[0:2] == ".0" || std[0:2] == ".9") {
512 p = formatNano(t.Nanosecond(), len(std)-1, std[1] == '9')
513 }
514 }
515 b.WriteString(p)
516 layout = suffix
517 }
518 return b.String()
519 }
520
521 var errBad = errors.New("bad value for field") // placeholder not passed to user
522
523 // ParseError describes a problem parsing a time string.
524 type ParseError struct {
525 Layout string
526 Value string
527 LayoutElem string
528 ValueElem string
529 Message string
530 }
531
532 func quote(s string) string {
533 return "\"" + s + "\""
534 }
535
536 // Error returns the string representation of a ParseError.
537 func (e *ParseError) Error() string {
538 if e.Message == "" {
539 return "parsing time " +
540 quote(e.Value) + " as " +
541 quote(e.Layout) + ": cannot parse " +
542 quote(e.ValueElem) + " as " +
543 quote(e.LayoutElem)
544 }
545 return "parsing time " +
546 quote(e.Value) + e.Message
547 }
548
549 // isDigit returns true if s[i] is a decimal digit, false if not or
550 // if s[i] is out of range.
551 func isDigit(s string, i int) bool {
552 if len(s) <= i {
553 return false
554 }
555 c := s[i]
556 return '0' <= c && c <= '9'
557 }
558
559 // getnum parses s[0:1] or s[0:2] (fixed forces the latter)
560 // as a decimal integer and returns the integer and the
561 // remainder of the string.
562 func getnum(s string, fixed bool) (int, string, error) {
563 if !isDigit(s, 0) {
564 return 0, s, errBad
565 }
566 if !isDigit(s, 1) {
567 if fixed {
568 return 0, s, errBad
569 }
570 return int(s[0] - '0'), s[1:], nil
571 }
572 return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
573 }
574
575 func cutspace(s string) string {
576 for len(s) > 0 && s[0] == ' ' {
577 s = s[1:]
578 }
579 return s
580 }
581
582 // skip removes the given prefix from value,
583 // treating runs of space characters as equivalent.
584 func skip(value, prefix string) (string, error) {
585 for len(prefix) > 0 {
586 if prefix[0] == ' ' {
587 if len(value) > 0 && value[0] != ' ' {
588 return "", errBad
589 }
590 prefix = cutspace(prefix)
591 value = cutspace(value)
592 continue
593 }
594 if len(value) == 0 || value[0] != prefix[0] {
595 return "", errBad
596 }
597 prefix = prefix[1:]
598 value = value[1:]
599 }
600 return value, nil
601 }
602
603 // Parse parses a formatted string and returns the time value it represents.
604 // The layout defines the format by showing the representation of the
605 // standard time,
606 // Mon Jan 2 15:04:05 -0700 MST 2006
607 // which is then used to describe the string to be parsed. Predefined layouts
608 // ANSIC, UnixDate, RFC3339 and others describe standard representations. For
609 // more information about the formats and the definition of the standard
610 // time, see the documentation for ANSIC.
611 //
612 // Elements omitted from the value are assumed to be zero or, when
613 // zero is impossible, one, so parsing "3:04pm" returns the time
614 // corresponding to Jan 1, year 0, 15:04:00 UTC.
615 // Years must be in the range 0000..9999. The day of the week is checked
616 // for syntax but it is otherwise ignored.
617 func Parse(layout, value string) (Time, error) {
618 alayout, avalue := layout, value
619 rangeErrString := "" // set if a value is out of range
620 amSet := false // do we need to subtract 12 from the hour for midnight?
621 pmSet := false // do we need to add 12 to the hour?
622
623 // Time being constructed.
624 var (
625 year int
626 month int = 1 // January
627 day int = 1
628 hour int
629 min int
630 sec int
631 nsec int
632 z *Location
633 zoneOffset int = -1
634 zoneName string
635 )
636
637 // Each iteration processes one std value.
638 for {
639 var err error
640 prefix, std, suffix := nextStdChunk(layout)
641 value, err = skip(value, prefix)
642 if err != nil {
643 return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
644 }
645 if len(std) == 0 {
646 if len(value) != 0 {
647 return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
648 }
649 break
650 }
651 layout = suffix
652 var p string
653 switch std {
654 case stdYear:
655 if len(value) < 2 {
656 err = errBad
657 break
658 }
659 p, value = value[0:2], value[2:]
660 year, err = atoi(p)
661 if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
662 year += 1900
663 } else {
664 year += 2000
665 }
666 case stdLongYear:
667 if len(value) < 4 || !isDigit(value, 0) {
668 err = errBad
669 break
670 }
671 p, value = value[0:4], value[4:]
672 year, err = atoi(p)
673 case stdMonth:
674 month, value, err = lookup(shortMonthNames, value)
675 case stdLongMonth:
676 month, value, err = lookup(longMonthNames, value)
677 case stdNumMonth, stdZeroMonth:
678 month, value, err = getnum(value, std == stdZeroMonth)
679 if month <= 0 || 12 < month {
680 rangeErrString = "month"
681 }
682 case stdWeekDay:
683 // Ignore weekday except for error checking.
684 _, value, err = lookup(shortDayNames, value)
685 case stdLongWeekDay:
686 _, value, err = lookup(longDayNames, value)
687 case stdDay, stdUnderDay, stdZeroDay:
688 if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
689 value = value[1:]
690 }
691 day, value, err = getnum(value, std == stdZeroDay)
692 if day < 0 || 31 < day {
693 rangeErrString = "day"
694 }
695 case stdHour:
696 hour, value, err = getnum(value, false)
697 if hour < 0 || 24 <= hour {
698 rangeErrString = "hour"
699 }
700 case stdHour12, stdZeroHour12:
701 hour, value, err = getnum(value, std == stdZeroHour12)
702 if hour < 0 || 12 < hour {
703 rangeErrString = "hour"
704 }
705 case stdMinute, stdZeroMinute:
706 min, value, err = getnum(value, std == stdZeroMinute)
707 if min < 0 || 60 <= min {
708 rangeErrString = "minute"
709 }
710 case stdSecond, stdZeroSecond:
711 sec, value, err = getnum(value, std == stdZeroSecond)
712 if sec < 0 || 60 <= sec {
713 rangeErrString = "second"
714 }
715 // Special case: do we have a fractional second but no
716 // fractional second in the format?
717 if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
718 _, std, _ := nextStdChunk(layout)
719 if len(std) > 0 && std[0] == '.' && isDigit(std, 1) {
720 // Fractional second in the layout; proceed normally
721 break
722 }
723 // No fractional second in the layout but we have one in the input.
724 n := 2
725 for ; n < len(value) && isDigit(value, n); n++ {
726 }
727 nsec, rangeErrString, err = parseNanoseconds(value, n)
728 value = value[n:]
729 }
730 case stdPM:
731 if len(value) < 2 {
732 err = errBad
733 break
734 }
735 p, value = value[0:2], value[2:]
736 switch p {
737 case "PM":
738 pmSet = true
739 case "AM":
740 amSet = true
741 default:
742 err = errBad
743 }
744 case stdpm:
745 if len(value) < 2 {
746 err = errBad
747 break
748 }
749 p, value = value[0:2], value[2:]
750 switch p {
751 case "pm":
752 pmSet = true
753 case "am":
754 amSet = true
755 default:
756 err = errBad
757 }
758 case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
759 if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' {
760 value = value[1:]
761 z = UTC
762 break
763 }
764 var sign, hour, min string
765 if std == stdISO8601ColonTZ || std == stdNumColonTZ {
766 if len(value) < 6 {
767 err = errBad
768 break
769 }
770 if value[3] != ':' {
771 err = errBad
772 break
773 }
774 sign, hour, min, value = value[0:1], value[1:3], value[4:6], value[6:]
775 } else if std == stdNumShortTZ {
776 if len(value) < 3 {
777 err = errBad
778 break
779 }
780 sign, hour, min, value = value[0:1], value[1:3], "00", value[3:]
781 } else {
782 if len(value) < 5 {
783 err = errBad
784 break
785 }
786 sign, hour, min, value = value[0:1], value[1:3], value[3:5], value[5:]
787 }
788 var hr, mm int
789 hr, err = atoi(hour)
790 if err == nil {
791 mm, err = atoi(min)
792 }
793 zoneOffset = (hr*60 + mm) * 60 // offset is in seconds
794 switch sign[0] {
795 case '+':
796 case '-':
797 zoneOffset = -zoneOffset
798 default:
799 err = errBad
800 }
801 case stdTZ:
802 // Does it look like a time zone?
803 if len(value) >= 3 && value[0:3] == "UTC" {
804 z = UTC
805 value = value[3:]
806 break
807 }
808
809 if len(value) >= 3 && value[2] == 'T' {
810 p, value = value[0:3], value[3:]
811 } else if len(value) >= 4 && value[3] == 'T' {
812 p, value = value[0:4], value[4:]
813 } else {
814 err = errBad
815 break
816 }
817 for i := 0; i < len(p); i++ {
818 if p[i] < 'A' || 'Z' < p[i] {
819 err = errBad
820 }
821 }
822 if err != nil {
823 break
824 }
825 // It's a valid format.
826 zoneName = p
827 default:
828 if len(value) < len(std) {
829 err = errBad
830 break
831 }
832 if len(std) >= 2 && std[0:2] == ".0" {
833 nsec, rangeErrString, err = parseNanoseconds(value, len(std))
834 value = value[len(std):]
835 }
836 }
837 if rangeErrString != "" {
838 return Time{}, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
839 }
840 if err != nil {
841 return Time{}, &ParseError{alayout, avalue, std, value, ""}
842 }
843 }
844 if pmSet && hour < 12 {
845 hour += 12
846 } else if amSet && hour == 12 {
847 hour = 0
848 }
849
850 // TODO: be more aggressive checking day?
851 if z != nil {
852 return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
853 }
854
855 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
856 if zoneOffset != -1 {
857 t.sec -= int64(zoneOffset)
858
859 // Look for local zone with the given offset.
860 // If that zone was in effect at the given time, use it.
861 name, offset, _, _, _ := Local.lookup(t.sec + internalToUnix)
862 if offset == zoneOffset && (zoneName == "" || name == zoneName) {
863 t.loc = Local
864 return t, nil
865 }
866
867 // Otherwise create fake zone to record offset.
868 t.loc = FixedZone(zoneName, zoneOffset)
869 return t, nil
870 }
871
872 if zoneName != "" {
873 // Look for local zone with the given offset.
874 // If that zone was in effect at the given time, use it.
875 offset, _, ok := Local.lookupName(zoneName)
876 if ok {
877 name, off, _, _, _ := Local.lookup(t.sec + internalToUnix - int64(offset))
878 if name == zoneName && off == offset {
879 t.sec -= int64(offset)
880 t.loc = Local
881 return t, nil
882 }
883 }
884
885 // Otherwise, create fake zone with unknown offset.
886 t.loc = FixedZone(zoneName, 0)
887 return t, nil
888 }
889
890 // Otherwise, fall back to UTC.
891 return t, nil
892 }
893
894 func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
895 if value[0] != '.' {
896 err = errBad
897 return
898 }
899 ns, err = atoi(value[1:nbytes])
900 if err != nil {
901 return
902 }
903 if ns < 0 || 1e9 <= ns {
904 rangeErrString = "fractional second"
905 return
906 }
907 // We need nanoseconds, which means scaling by the number
908 // of missing digits in the format, maximum length 10. If it's
909 // longer than 10, we won't scale.
910 scaleDigits := 10 - nbytes
911 for i := 0; i < scaleDigits; i++ {
912 ns *= 10
913 }
914 return
915 }
916
917 var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
918
919 // leadingInt consumes the leading [0-9]* from s.
920 func leadingInt(s string) (x int, rem string, err error) {
921 i := 0
922 for ; i < len(s); i++ {
923 c := s[i]
924 if c < '0' || c > '9' {
925 break
926 }
927 if x >= (1<<31-10)/10 {
928 // overflow
929 return 0, "", errLeadingInt
930 }
931 x = x*10 + int(c) - '0'
932 }
933 return x, s[i:], nil
934 }
935
936 var unitMap = map[string]float64{
937 "ns": float64(Nanosecond),
938 "us": float64(Microsecond),
939 "µs": float64(Microsecond), // U+00B5 = micro symbol
940 "μs": float64(Microsecond), // U+03BC = Greek letter mu
941 "ms": float64(Millisecond),
942 "s": float64(Second),
943 "m": float64(Minute),
944 "h": float64(Hour),
945 }
946
947 // ParseDuration parses a duration string.
948 // A duration string is a possibly signed sequence of
949 // decimal numbers, each with optional fraction and a unit suffix,
950 // such as "300ms", "-1.5h" or "2h45m".
951 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
952 func ParseDuration(s string) (Duration, error) {
953 // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
954 orig := s
955 f := float64(0)
956 neg := false
957
958 // Consume [-+]?
959 if s != "" {
960 c := s[0]
961 if c == '-' || c == '+' {
962 neg = c == '-'
963 s = s[1:]
964 }
965 }
966 // Special case: if all that is left is "0", this is zero.
967 if s == "0" {
968 return 0, nil
969 }
970 if s == "" {
971 return 0, errors.New("time: invalid duration " + orig)
972 }
973 for s != "" {
974 g := float64(0) // this element of the sequence
975
976 var x int
977 var err error
978
979 // The next character must be [0-9.]
980 if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
981 return 0, errors.New("time: invalid duration " + orig)
982 }
983 // Consume [0-9]*
984 pl := len(s)
985 x, s, err = leadingInt(s)
986 if err != nil {
987 return 0, errors.New("time: invalid duration " + orig)
988 }
989 g = float64(x)
990 pre := pl != len(s) // whether we consumed anything before a period
991
992 // Consume (\.[0-9]*)?
993 post := false
994 if s != "" && s[0] == '.' {
995 s = s[1:]
996 pl := len(s)
997 x, s, err = leadingInt(s)
998 if err != nil {
999 return 0, errors.New("time: invalid duration " + orig)
1000 }
1001 scale := 1
1002 for n := pl - len(s); n > 0; n-- {
1003 scale *= 10
1004 }
1005 g += float64(x) / float64(scale)
1006 post = pl != len(s)
1007 }
1008 if !pre && !post {
1009 // no digits (e.g. ".s" or "-.s")
1010 return 0, errors.New("time: invalid duration " + orig)
1011 }
1012
1013 // Consume unit.
1014 i := 0
1015 for ; i < len(s); i++ {
1016 c := s[i]
1017 if c == '.' || ('0' <= c && c <= '9') {
1018 break
1019 }
1020 }
1021 if i == 0 {
1022 return 0, errors.New("time: missing unit in duration " + orig)
1023 }
1024 u := s[:i]
1025 s = s[i:]
1026 unit, ok := unitMap[u]
1027 if !ok {
1028 return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
1029 }
1030
1031 f += g * unit
1032 }
1033
1034 if neg {
1035 f = -f
1036 }
1037 return Duration(f), nil
1038 }