libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
[official-gcc.git] / libgo / go / time / format.go
blob04e79f32dcd4d2a080a5c857a7711ca2598abd58
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 // 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 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, defined to be
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 || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
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 // defined to be
680 // Mon Jan 2 15:04:05 -0700 MST 2006
681 // would be interpreted if it were the value; it serves as an example of
682 // the input format. The same interpretation will then be made to the
683 // input string.
684 // Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
685 // and convenient representations of the reference time. For more information
686 // about the formats and the definition of the reference time, see the
687 // documentation for ANSIC and the other constants defined by this package.
689 // Elements omitted from the value are assumed to be zero or, when
690 // zero is impossible, one, so parsing "3:04pm" returns the time
691 // corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
692 // 0, this time is before the zero Time).
693 // Years must be in the range 0000..9999. The day of the week is checked
694 // for syntax but it is otherwise ignored.
696 // In the absence of a time zone indicator, Parse returns a time in UTC.
698 // When parsing a time with a zone offset like -0700, if the offset corresponds
699 // to a time zone used by the current location (Local), then Parse uses that
700 // location and zone in the returned time. Otherwise it records the time as
701 // being in a fabricated location with time fixed at the given zone offset.
703 // When parsing a time with a zone abbreviation like MST, if the zone abbreviation
704 // has a defined offset in the current location, then that offset is used.
705 // The zone abbreviation "UTC" is recognized as UTC regardless of location.
706 // If the zone abbreviation is unknown, Parse records the time as being
707 // in a fabricated location with the given zone abbreviation and a zero offset.
708 // This choice means that such a time can be parsed and reformatted with the
709 // same layout losslessly, but the exact instant used in the representation will
710 // differ by the actual zone offset. To avoid such problems, prefer time layouts
711 // that use a numeric zone offset, or use ParseInLocation.
712 func Parse(layout, value string) (Time, error) {
713 return parse(layout, value, UTC, Local)
716 // ParseInLocation is like Parse but differs in two important ways.
717 // First, in the absence of time zone information, Parse interprets a time as UTC;
718 // ParseInLocation interprets the time as in the given location.
719 // Second, when given a zone offset or abbreviation, Parse tries to match it
720 // against the Local location; ParseInLocation uses the given location.
721 func ParseInLocation(layout, value string, loc *Location) (Time, error) {
722 return parse(layout, value, loc, loc)
725 func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
726 alayout, avalue := layout, value
727 rangeErrString := "" // set if a value is out of range
728 amSet := false // do we need to subtract 12 from the hour for midnight?
729 pmSet := false // do we need to add 12 to the hour?
731 // Time being constructed.
732 var (
733 year int
734 month int = 1 // January
735 day int = 1
736 hour int
737 min int
738 sec int
739 nsec int
740 z *Location
741 zoneOffset int = -1
742 zoneName string
745 // Each iteration processes one std value.
746 for {
747 var err error
748 prefix, std, suffix := nextStdChunk(layout)
749 stdstr := layout[len(prefix) : len(layout)-len(suffix)]
750 value, err = skip(value, prefix)
751 if err != nil {
752 return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
754 if std == 0 {
755 if len(value) != 0 {
756 return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
758 break
760 layout = suffix
761 var p string
762 switch std & stdMask {
763 case stdYear:
764 if len(value) < 2 {
765 err = errBad
766 break
768 p, value = value[0:2], value[2:]
769 year, err = atoi(p)
770 if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
771 year += 1900
772 } else {
773 year += 2000
775 case stdLongYear:
776 if len(value) < 4 || !isDigit(value, 0) {
777 err = errBad
778 break
780 p, value = value[0:4], value[4:]
781 year, err = atoi(p)
782 case stdMonth:
783 month, value, err = lookup(shortMonthNames, value)
784 case stdLongMonth:
785 month, value, err = lookup(longMonthNames, value)
786 case stdNumMonth, stdZeroMonth:
787 month, value, err = getnum(value, std == stdZeroMonth)
788 if month <= 0 || 12 < month {
789 rangeErrString = "month"
791 case stdWeekDay:
792 // Ignore weekday except for error checking.
793 _, value, err = lookup(shortDayNames, value)
794 case stdLongWeekDay:
795 _, value, err = lookup(longDayNames, value)
796 case stdDay, stdUnderDay, stdZeroDay:
797 if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
798 value = value[1:]
800 day, value, err = getnum(value, std == stdZeroDay)
801 if day < 0 || 31 < day {
802 rangeErrString = "day"
804 case stdHour:
805 hour, value, err = getnum(value, false)
806 if hour < 0 || 24 <= hour {
807 rangeErrString = "hour"
809 case stdHour12, stdZeroHour12:
810 hour, value, err = getnum(value, std == stdZeroHour12)
811 if hour < 0 || 12 < hour {
812 rangeErrString = "hour"
814 case stdMinute, stdZeroMinute:
815 min, value, err = getnum(value, std == stdZeroMinute)
816 if min < 0 || 60 <= min {
817 rangeErrString = "minute"
819 case stdSecond, stdZeroSecond:
820 sec, value, err = getnum(value, std == stdZeroSecond)
821 if sec < 0 || 60 <= sec {
822 rangeErrString = "second"
824 // Special case: do we have a fractional second but no
825 // fractional second in the format?
826 if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
827 _, std, _ = nextStdChunk(layout)
828 std &= stdMask
829 if std == stdFracSecond0 || std == stdFracSecond9 {
830 // Fractional second in the layout; proceed normally
831 break
833 // No fractional second in the layout but we have one in the input.
834 n := 2
835 for ; n < len(value) && isDigit(value, n); n++ {
837 nsec, rangeErrString, err = parseNanoseconds(value, n)
838 value = value[n:]
840 case stdPM:
841 if len(value) < 2 {
842 err = errBad
843 break
845 p, value = value[0:2], value[2:]
846 switch p {
847 case "PM":
848 pmSet = true
849 case "AM":
850 amSet = true
851 default:
852 err = errBad
854 case stdpm:
855 if len(value) < 2 {
856 err = errBad
857 break
859 p, value = value[0:2], value[2:]
860 switch p {
861 case "pm":
862 pmSet = true
863 case "am":
864 amSet = true
865 default:
866 err = errBad
868 case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
869 if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
870 value = value[1:]
871 z = UTC
872 break
874 var sign, hour, min, seconds string
875 if std == stdISO8601ColonTZ || std == stdNumColonTZ {
876 if len(value) < 6 {
877 err = errBad
878 break
880 if value[3] != ':' {
881 err = errBad
882 break
884 sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
885 } else if std == stdNumShortTZ {
886 if len(value) < 3 {
887 err = errBad
888 break
890 sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
891 } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
892 if len(value) < 9 {
893 err = errBad
894 break
896 if value[3] != ':' || value[6] != ':' {
897 err = errBad
898 break
900 sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
901 } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
902 if len(value) < 7 {
903 err = errBad
904 break
906 sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
907 } else {
908 if len(value) < 5 {
909 err = errBad
910 break
912 sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
914 var hr, mm, ss int
915 hr, err = atoi(hour)
916 if err == nil {
917 mm, err = atoi(min)
919 if err == nil {
920 ss, err = atoi(seconds)
922 zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
923 switch sign[0] {
924 case '+':
925 case '-':
926 zoneOffset = -zoneOffset
927 default:
928 err = errBad
930 case stdTZ:
931 // Does it look like a time zone?
932 if len(value) >= 3 && value[0:3] == "UTC" {
933 z = UTC
934 value = value[3:]
935 break
937 n, ok := parseTimeZone(value)
938 if !ok {
939 err = errBad
940 break
942 zoneName, value = value[:n], value[n:]
944 case stdFracSecond0:
945 // stdFracSecond0 requires the exact number of digits as specified in
946 // the layout.
947 ndigit := 1 + (std >> stdArgShift)
948 if len(value) < ndigit {
949 err = errBad
950 break
952 nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
953 value = value[ndigit:]
955 case stdFracSecond9:
956 if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
957 // Fractional second omitted.
958 break
960 // Take any number of digits, even more than asked for,
961 // because it is what the stdSecond case would do.
962 i := 0
963 for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
966 nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
967 value = value[1+i:]
969 if rangeErrString != "" {
970 return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
972 if err != nil {
973 return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
976 if pmSet && hour < 12 {
977 hour += 12
978 } else if amSet && hour == 12 {
979 hour = 0
982 if z != nil {
983 return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
986 if zoneOffset != -1 {
987 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
988 t.sec -= int64(zoneOffset)
990 // Look for local zone with the given offset.
991 // If that zone was in effect at the given time, use it.
992 name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
993 if offset == zoneOffset && (zoneName == "" || name == zoneName) {
994 t.loc = local
995 return t, nil
998 // Otherwise create fake zone to record offset.
999 t.loc = FixedZone(zoneName, zoneOffset)
1000 return t, nil
1003 if zoneName != "" {
1004 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
1005 // Look for local zone with the given offset.
1006 // If that zone was in effect at the given time, use it.
1007 offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
1008 if ok {
1009 t.sec -= int64(offset)
1010 t.loc = local
1011 return t, nil
1014 // Otherwise, create fake zone with unknown offset.
1015 if len(zoneName) > 3 && zoneName[:3] == "GMT" {
1016 offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
1017 offset *= 3600
1019 t.loc = FixedZone(zoneName, offset)
1020 return t, nil
1023 // Otherwise, fall back to default.
1024 return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
1027 // parseTimeZone parses a time zone string and returns its length. Time zones
1028 // are human-generated and unpredictable. We can't do precise error checking.
1029 // On the other hand, for a correct parse there must be a time zone at the
1030 // beginning of the string, so it's almost always true that there's one
1031 // there. We look at the beginning of the string for a run of upper-case letters.
1032 // If there are more than 5, it's an error.
1033 // If there are 4 or 5 and the last is a T, it's a time zone.
1034 // If there are 3, it's a time zone.
1035 // Otherwise, other than special cases, it's not a time zone.
1036 // GMT is special because it can have an hour offset.
1037 func parseTimeZone(value string) (length int, ok bool) {
1038 if len(value) < 3 {
1039 return 0, false
1041 // Special case 1: ChST and MeST are the only zones with a lower-case letter.
1042 if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
1043 return 4, true
1045 // Special case 2: GMT may have an hour offset; treat it specially.
1046 if value[:3] == "GMT" {
1047 length = parseGMT(value)
1048 return length, true
1050 // How many upper-case letters are there? Need at least three, at most five.
1051 var nUpper int
1052 for nUpper = 0; nUpper < 6; nUpper++ {
1053 if nUpper >= len(value) {
1054 break
1056 if c := value[nUpper]; c < 'A' || 'Z' < c {
1057 break
1060 switch nUpper {
1061 case 0, 1, 2, 6:
1062 return 0, false
1063 case 5: // Must end in T to match.
1064 if value[4] == 'T' {
1065 return 5, true
1067 case 4: // Must end in T to match.
1068 if value[3] == 'T' {
1069 return 4, true
1071 case 3:
1072 return 3, true
1074 return 0, false
1077 // parseGMT parses a GMT time zone. The input string is known to start "GMT".
1078 // The function checks whether that is followed by a sign and a number in the
1079 // range -14 through 12 excluding zero.
1080 func parseGMT(value string) int {
1081 value = value[3:]
1082 if len(value) == 0 {
1083 return 3
1085 sign := value[0]
1086 if sign != '-' && sign != '+' {
1087 return 3
1089 x, rem, err := leadingInt(value[1:])
1090 if err != nil {
1091 return 3
1093 if sign == '-' {
1094 x = -x
1096 if x == 0 || x < -14 || 12 < x {
1097 return 3
1099 return 3 + len(value) - len(rem)
1102 func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
1103 if value[0] != '.' {
1104 err = errBad
1105 return
1107 if ns, err = atoi(value[1:nbytes]); err != nil {
1108 return
1110 if ns < 0 || 1e9 <= ns {
1111 rangeErrString = "fractional second"
1112 return
1114 // We need nanoseconds, which means scaling by the number
1115 // of missing digits in the format, maximum length 10. If it's
1116 // longer than 10, we won't scale.
1117 scaleDigits := 10 - nbytes
1118 for i := 0; i < scaleDigits; i++ {
1119 ns *= 10
1121 return
1124 var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
1126 // leadingInt consumes the leading [0-9]* from s.
1127 func leadingInt(s string) (x int64, rem string, err error) {
1128 i := 0
1129 for ; i < len(s); i++ {
1130 c := s[i]
1131 if c < '0' || c > '9' {
1132 break
1134 if x >= (1<<63-10)/10 {
1135 // overflow
1136 return 0, "", errLeadingInt
1138 x = x*10 + int64(c) - '0'
1140 return x, s[i:], nil
1143 var unitMap = map[string]float64{
1144 "ns": float64(Nanosecond),
1145 "us": float64(Microsecond),
1146 "µs": float64(Microsecond), // U+00B5 = micro symbol
1147 "μs": float64(Microsecond), // U+03BC = Greek letter mu
1148 "ms": float64(Millisecond),
1149 "s": float64(Second),
1150 "m": float64(Minute),
1151 "h": float64(Hour),
1154 // ParseDuration parses a duration string.
1155 // A duration string is a possibly signed sequence of
1156 // decimal numbers, each with optional fraction and a unit suffix,
1157 // such as "300ms", "-1.5h" or "2h45m".
1158 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
1159 func ParseDuration(s string) (Duration, error) {
1160 // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
1161 orig := s
1162 f := float64(0)
1163 neg := false
1165 // Consume [-+]?
1166 if s != "" {
1167 c := s[0]
1168 if c == '-' || c == '+' {
1169 neg = c == '-'
1170 s = s[1:]
1173 // Special case: if all that is left is "0", this is zero.
1174 if s == "0" {
1175 return 0, nil
1177 if s == "" {
1178 return 0, errors.New("time: invalid duration " + orig)
1180 for s != "" {
1181 g := float64(0) // this element of the sequence
1183 var x int64
1184 var err error
1186 // The next character must be [0-9.]
1187 if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
1188 return 0, errors.New("time: invalid duration " + orig)
1190 // Consume [0-9]*
1191 pl := len(s)
1192 x, s, err = leadingInt(s)
1193 if err != nil {
1194 return 0, errors.New("time: invalid duration " + orig)
1196 g = float64(x)
1197 pre := pl != len(s) // whether we consumed anything before a period
1199 // Consume (\.[0-9]*)?
1200 post := false
1201 if s != "" && s[0] == '.' {
1202 s = s[1:]
1203 pl := len(s)
1204 x, s, err = leadingInt(s)
1205 if err != nil {
1206 return 0, errors.New("time: invalid duration " + orig)
1208 scale := 1.0
1209 for n := pl - len(s); n > 0; n-- {
1210 scale *= 10
1212 g += float64(x) / scale
1213 post = pl != len(s)
1215 if !pre && !post {
1216 // no digits (e.g. ".s" or "-.s")
1217 return 0, errors.New("time: invalid duration " + orig)
1220 // Consume unit.
1221 i := 0
1222 for ; i < len(s); i++ {
1223 c := s[i]
1224 if c == '.' || ('0' <= c && c <= '9') {
1225 break
1228 if i == 0 {
1229 return 0, errors.New("time: missing unit in duration " + orig)
1231 u := s[:i]
1232 s = s[i:]
1233 unit, ok := unitMap[u]
1234 if !ok {
1235 return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
1238 f += g * unit
1241 if neg {
1242 f = -f
1244 if f < float64(-1<<63) || f > float64(1<<63-1) {
1245 return 0, errors.New("time: overflow parsing duration")
1247 return Duration(f), nil