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