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