blob: 04e79f32dcd4d2a080a5c857a7711ca2598abd58 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// 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
5package time
6
7import "errors"
8
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.
20//
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.
24//
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.
33//
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
42const (
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"
59)
60
61const (
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
95
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
100)
101
102// std0x records the std values for "01", "02", ..., "06".
103var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
104
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".
107func startsWithLowerCase(str string) bool {
108 if len(str) == 0 {
109 return false
110 }
111 c := str[0]
112 return 'a' <= c && c <= 'z'
113}
114
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.
117func 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:]
124 }
125 if !startsWithLowerCase(layout[i+3:]) {
126 return layout[0:i], stdMonth, layout[i+3:]
127 }
128 }
129
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:]
135 }
136 if !startsWithLowerCase(layout[i+3:]) {
137 return layout[0:i], stdWeekDay, layout[i+3:]
138 }
139 }
140 if layout[i:i+3] == "MST" {
141 return layout[0:i], stdTZ, layout[i+3:]
142 }
143 }
144
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:]
148 }
149
150 case '1': // 15, 1
151 if len(layout) >= i+2 && layout[i+1] == '5' {
152 return layout[0:i], stdHour, layout[i+2:]
153 }
154 return layout[0:i], stdNumMonth, layout[i+1:]
155
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:]
159 }
160 return layout[0:i], stdDay, layout[i+1:]
161
162 case '_': // _2
163 if len(layout) >= i+2 && layout[i+1] == '2' {
164 return layout[0:i], stdUnderDay, layout[i+2:]
165 }
166
167 case '3':
168 return layout[0:i], stdHour12, layout[i+1:]
169
170 case '4':
171 return layout[0:i], stdMinute, layout[i+1:]
172
173 case '5':
174 return layout[0:i], stdSecond, layout[i+1:]
175
176 case 'P': // PM
177 if len(layout) >= i+2 && layout[i+1] == 'M' {
178 return layout[0:i], stdPM, layout[i+2:]
179 }
180
181 case 'p': // pm
182 if len(layout) >= i+2 && layout[i+1] == 'm' {
183 return layout[0:i], stdpm, layout[i+2:]
184 }
185
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:]
189 }
190 if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
191 return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
192 }
193 if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
194 return layout[0:i], stdNumTZ, layout[i+5:]
195 }
196 if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
197 return layout[0:i], stdNumColonTZ, layout[i+6:]
198 }
199 if len(layout) >= i+3 && layout[i:i+3] == "-07" {
200 return layout[0:i], stdNumShortTZ, layout[i+3:]
201 }
202
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:]
206 }
207 if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
208 return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
209 }
210 if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
211 return layout[0:i], stdISO8601TZ, layout[i+5:]
212 }
213 if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
214 return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
215 }
216
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 {
222 j++
223 }
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
229 }
230 std |= (j - (i + 1)) << stdArgShift
231 return layout[0:i], std, layout[j:]
232 }
233 }
234 }
235 }
236 return layout, 0, ""
237}
238
239var longDayNames = []string{
240 "Sunday",
241 "Monday",
242 "Tuesday",
243 "Wednesday",
244 "Thursday",
245 "Friday",
246 "Saturday",
247}
248
249var shortDayNames = []string{
250 "Sun",
251 "Mon",
252 "Tue",
253 "Wed",
254 "Thu",
255 "Fri",
256 "Sat",
257}
258
259var 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",
273}
274
275var 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",
289}
290
291// match returns true if s1 and s2 match ignoring case.
292// It is assumed s1 and s2 are the same length.
293func 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
303 }
304 }
305 }
306 return true
307}
308
309func 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
313 }
314 }
315 return -1, val, errBad
316}
317
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.
322func appendUint(b []byte, x uint, pad byte) []byte {
323 if x < 10 {
324 if pad != 0 {
325 b = append(b, pad)
326 }
327 return append(b, byte('0'+x))
328 }
329 if x < 100 {
330 b = append(b, byte('0'+x/10))
331 b = append(b, byte('0'+x%10))
332 return b
333 }
334
335 var buf [32]byte
336 n := len(buf)
337 if x == 0 {
338 return append(b, '0')
339 }
340 for x >= 10 {
341 n--
342 buf[n] = byte(x%10 + '0')
343 x /= 10
344 }
345 n--
346 buf[n] = byte(x + '0')
347 return append(b, buf[n:]...)
348}
349
350// Never printed, just needs to be non-nil for return by atoi.
351var atoiError = errors.New("time: invalid number")
352
353// Duplicates functionality in strconv, but avoids dependency.
354func 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:]
359 }
360 q, rem, err := leadingInt(s)
361 x = int(q)
362 if err != nil || rem != "" {
363 return 0, atoiError
364 }
365 if neg {
366 x = -x
367 }
368 return x, nil
369}
370
371// formatNano appends a fractional second, as nanoseconds, to b
372// and returns the result.
373func 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
380 }
381
382 if n > 9 {
383 n = 9
384 }
385 if trim {
386 for n > 0 && buf[n-1] == '0' {
387 n--
388 }
389 if n == 0 {
390 return b
391 }
392 }
393 b = append(b, '.')
394 return append(b, buf[:n]...)
395}
396
397// String returns the time formatted using the format string
398// "2006-01-02 15:04:05.999999999 -0700 MST"
399func (t Time) String() string {
400 return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
401}
402
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.
414func (t Time) Format(layout string) string {
415 var (
416 name, offset, abs = t.locabs()
417
418 year int = -1
419 month Month
420 day int
421 hour int = -1
422 min int
423 sec int
424
425 b []byte
426 buf [64]byte
427 )
428 max := len(layout) + 10
429 if max <= len(buf) {
430 b = buf[:0]
431 } else {
432 b = make([]byte, 0, max)
433 }
434 // Each iteration generates one std value.
435 for layout != "" {
436 prefix, std, suffix := nextStdChunk(layout)
437 if prefix != "" {
438 b = append(b, prefix...)
439 }
440 if std == 0 {
441 break
442 }
443 layout = suffix
444
445 // Compute year, month, day if needed.
446 if year < 0 && std&stdNeedDate != 0 {
447 year, month, day, _ = absDate(abs, true)
448 }
449
450 // Compute hour, minute, second if needed.
451 if hour < 0 && std&stdNeedClock != 0 {
452 hour, min, sec = absClock(abs)
453 }
454
455 switch std & stdMask {
456 case stdYear:
457 y := year
458 if y < 0 {
459 y = -y
460 }
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')
484 }
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
513 }
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
520 }
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"...)
535 }
536 case stdpm:
537 if hour >= 12 {
538 b = append(b, "pm"...)
539 } else {
540 b = append(b, "am"...)
541 }
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
548 }
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, '+')
557 }
558 b = appendUint(b, uint(zone/60), '0')
559 if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
560 b = append(b, ':')
561 }
562 b = appendUint(b, uint(zone%60), '0')
563
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, ':')
568 }
569 b = appendUint(b, uint(absoffset%60), '0')
570 }
571
572 case stdTZ:
573 if name != "" {
574 b = append(b, name...)
575 break
576 }
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, '+')
585 }
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)
590 }
591 }
592 return string(b)
593}
594
595var errBad = errors.New("bad value for field") // placeholder not passed to user
596
597// ParseError describes a problem parsing a time string.
598type ParseError struct {
599 Layout string
600 Value string
601 LayoutElem string
602 ValueElem string
603 Message string
604}
605
606func quote(s string) string {
607 return "\"" + s + "\""
608}
609
610// Error returns the string representation of a ParseError.
611func (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)
618 }
619 return "parsing time " +
620 quote(e.Value) + e.Message
621}
622
623// isDigit returns true if s[i] is a decimal digit, false if not or
624// if s[i] is out of range.
625func isDigit(s string, i int) bool {
626 if len(s) <= i {
627 return false
628 }
629 c := s[i]
630 return '0' <= c && c <= '9'
631}
632
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.
636func getnum(s string, fixed bool) (int, string, error) {
637 if !isDigit(s, 0) {
638 return 0, s, errBad
639 }
640 if !isDigit(s, 1) {
641 if fixed {
642 return 0, s, errBad
643 }
644 return int(s[0] - '0'), s[1:], nil
645 }
646 return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
647}
648
649func cutspace(s string) string {
650 for len(s) > 0 && s[0] == ' ' {
651 s = s[1:]
652 }
653 return s
654}
655
656// skip removes the given prefix from value,
657// treating runs of space characters as equivalent.
658func 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
663 }
664 prefix = cutspace(prefix)
665 value = cutspace(value)
666 continue
667 }
668 if len(value) == 0 || value[0] != prefix[0] {
669 return value, errBad
670 }
671 prefix = prefix[1:]
672 value = value[1:]
673 }
674 return value, nil
675}
676
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.
688//
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.
695//
696// In the absence of a time zone indicator, Parse returns a time in UTC.
697//
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.
702//
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.
712func Parse(layout, value string) (Time, error) {
713 return parse(layout, value, UTC, Local)
714}
715
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.
721func ParseInLocation(layout, value string, loc *Location) (Time, error) {
722 return parse(layout, value, loc, loc)
723}
724
725func 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?
730
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
743 )
744
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, ""}
753 }
754 if std == 0 {
755 if len(value) != 0 {
756 return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
757 }
758 break
759 }
760 layout = suffix
761 var p string
762 switch std & stdMask {
763 case stdYear:
764 if len(value) < 2 {
765 err = errBad
766 break
767 }
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
774 }
775 case stdLongYear:
776 if len(value) < 4 || !isDigit(value, 0) {
777 err = errBad
778 break
779 }
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"
790 }
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:]
799 }
800 day, value, err = getnum(value, std == stdZeroDay)
801 if day < 0 || 31 < day {
802 rangeErrString = "day"
803 }
804 case stdHour:
805 hour, value, err = getnum(value, false)
806 if hour < 0 || 24 <= hour {
807 rangeErrString = "hour"
808 }
809 case stdHour12, stdZeroHour12:
810 hour, value, err = getnum(value, std == stdZeroHour12)
811 if hour < 0 || 12 < hour {
812 rangeErrString = "hour"
813 }
814 case stdMinute, stdZeroMinute:
815 min, value, err = getnum(value, std == stdZeroMinute)
816 if min < 0 || 60 <= min {
817 rangeErrString = "minute"
818 }
819 case stdSecond, stdZeroSecond:
820 sec, value, err = getnum(value, std == stdZeroSecond)
821 if sec < 0 || 60 <= sec {
822 rangeErrString = "second"
823 }
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
832 }
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++ {
836 }
837 nsec, rangeErrString, err = parseNanoseconds(value, n)
838 value = value[n:]
839 }
840 case stdPM:
841 if len(value) < 2 {
842 err = errBad
843 break
844 }
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
853 }
854 case stdpm:
855 if len(value) < 2 {
856 err = errBad
857 break
858 }
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
867 }
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
873 }
874 var sign, hour, min, seconds string
875 if std == stdISO8601ColonTZ || std == stdNumColonTZ {
876 if len(value) < 6 {
877 err = errBad
878 break
879 }
880 if value[3] != ':' {
881 err = errBad
882 break
883 }
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
889 }
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
895 }
896 if value[3] != ':' || value[6] != ':' {
897 err = errBad
898 break
899 }
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
905 }
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
911 }
912 sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
913 }
914 var hr, mm, ss int
915 hr, err = atoi(hour)
916 if err == nil {
917 mm, err = atoi(min)
918 }
919 if err == nil {
920 ss, err = atoi(seconds)
921 }
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
929 }
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
936 }
937 n, ok := parseTimeZone(value)
938 if !ok {
939 err = errBad
940 break
941 }
942 zoneName, value = value[:n], value[n:]
943
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
951 }
952 nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
953 value = value[ndigit:]
954
955 case stdFracSecond9:
956 if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
957 // Fractional second omitted.
958 break
959 }
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' {
964 i++
965 }
966 nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
967 value = value[1+i:]
968 }
969 if rangeErrString != "" {
970 return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
971 }
972 if err != nil {
973 return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
974 }
975 }
976 if pmSet && hour < 12 {
977 hour += 12
978 } else if amSet && hour == 12 {
979 hour = 0
980 }
981
982 if z != nil {
983 return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
984 }
985
986 if zoneOffset != -1 {
987 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
988 t.sec -= int64(zoneOffset)
989
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
996 }
997
998 // Otherwise create fake zone to record offset.
999 t.loc = FixedZone(zoneName, zoneOffset)
1000 return t, nil
1001 }
1002
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
1012 }
1013
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
1018 }
1019 t.loc = FixedZone(zoneName, offset)
1020 return t, nil
1021 }
1022
1023 // Otherwise, fall back to default.
1024 return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
1025}
1026
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.
1037func parseTimeZone(value string) (length int, ok bool) {
1038 if len(value) < 3 {
1039 return 0, false
1040 }
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
1044 }
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
1049 }
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
1055 }
1056 if c := value[nUpper]; c < 'A' || 'Z' < c {
1057 break
1058 }
1059 }
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
1066 }
1067 case 4: // Must end in T to match.
1068 if value[3] == 'T' {
1069 return 4, true
1070 }
1071 case 3:
1072 return 3, true
1073 }
1074 return 0, false
1075}
1076
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.
1080func parseGMT(value string) int {
1081 value = value[3:]
1082 if len(value) == 0 {
1083 return 3
1084 }
1085 sign := value[0]
1086 if sign != '-' && sign != '+' {
1087 return 3
1088 }
1089 x, rem, err := leadingInt(value[1:])
1090 if err != nil {
1091 return 3
1092 }
1093 if sign == '-' {
1094 x = -x
1095 }
1096 if x == 0 || x < -14 || 12 < x {
1097 return 3
1098 }
1099 return 3 + len(value) - len(rem)
1100}
1101
1102func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
1103 if value[0] != '.' {
1104 err = errBad
1105 return
1106 }
1107 if ns, err = atoi(value[1:nbytes]); err != nil {
1108 return
1109 }
1110 if ns < 0 || 1e9 <= ns {
1111 rangeErrString = "fractional second"
1112 return
1113 }
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
1120 }
1121 return
1122}
1123
1124var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
1125
1126// leadingInt consumes the leading [0-9]* from s.
1127func 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
1133 }
1134 if x >= (1<<63-10)/10 {
1135 // overflow
1136 return 0, "", errLeadingInt
1137 }
1138 x = x*10 + int64(c) - '0'
1139 }
1140 return x, s[i:], nil
1141}
1142
1143var 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),
1152}
1153
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".
1159func ParseDuration(s string) (Duration, error) {
1160 // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
1161 orig := s
1162 f := float64(0)
1163 neg := false
1164
1165 // Consume [-+]?
1166 if s != "" {
1167 c := s[0]
1168 if c == '-' || c == '+' {
1169 neg = c == '-'
1170 s = s[1:]
1171 }
1172 }
1173 // Special case: if all that is left is "0", this is zero.
1174 if s == "0" {
1175 return 0, nil
1176 }
1177 if s == "" {
1178 return 0, errors.New("time: invalid duration " + orig)
1179 }
1180 for s != "" {
1181 g := float64(0) // this element of the sequence
1182
1183 var x int64
1184 var err error
1185
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)
1189 }
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)
1195 }
1196 g = float64(x)
1197 pre := pl != len(s) // whether we consumed anything before a period
1198
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)
1207 }
1208 scale := 1.0
1209 for n := pl - len(s); n > 0; n-- {
1210 scale *= 10
1211 }
1212 g += float64(x) / scale
1213 post = pl != len(s)
1214 }
1215 if !pre && !post {
1216 // no digits (e.g. ".s" or "-.s")
1217 return 0, errors.New("time: invalid duration " + orig)
1218 }
1219
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
1226 }
1227 }
1228 if i == 0 {
1229 return 0, errors.New("time: missing unit in duration " + orig)
1230 }
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)
1236 }
1237
1238 f += g * unit
1239 }
1240
1241 if neg {
1242 f = -f
1243 }
1244 if f < float64(-1<<63) || f > float64(1<<63-1) {
1245 return 0, errors.New("time: overflow parsing duration")
1246 }
1247 return Duration(f), nil
1248}