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