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