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