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