github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/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 __2 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 buf := make([]byte, 0, 24) 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 := make([]byte, 0, 70) 530 buf = append(buf, "time.Date("...) 531 buf = appendInt(buf, t.Year(), 0) 532 month := t.Month() 533 if January <= month && month <= December { 534 buf = append(buf, ", time."...) 535 buf = append(buf, t.Month().String()...) 536 } else { 537 // It's difficult to construct a time.Time with a date outside the 538 // standard range but we might as well try to handle the case. 539 buf = appendInt(buf, int(month), 0) 540 } 541 buf = append(buf, ", "...) 542 buf = appendInt(buf, t.Day(), 0) 543 buf = append(buf, ", "...) 544 buf = appendInt(buf, t.Hour(), 0) 545 buf = append(buf, ", "...) 546 buf = appendInt(buf, t.Minute(), 0) 547 buf = append(buf, ", "...) 548 buf = appendInt(buf, t.Second(), 0) 549 buf = append(buf, ", "...) 550 buf = appendInt(buf, t.Nanosecond(), 0) 551 buf = append(buf, ", "...) 552 switch loc := t.Location(); loc { 553 case UTC, nil: 554 buf = append(buf, "time.UTC"...) 555 case Local: 556 buf = append(buf, "time.Local"...) 557 default: 558 // there are several options for how we could display this, none of 559 // which are great: 560 // 561 // - use Location(loc.name), which is not technically valid syntax 562 // - use LoadLocation(loc.name), which will cause a syntax error when 563 // embedded and also would require us to escape the string without 564 // importing fmt or strconv 565 // - try to use FixedZone, which would also require escaping the name 566 // and would represent e.g. "America/Los_Angeles" daylight saving time 567 // shifts inaccurately 568 // - use the pointer format, which is no worse than you'd get with the 569 // old fmt.Sprintf("%#v", t) format. 570 // 571 // Of these, Location(loc.name) is the least disruptive. This is an edge 572 // case we hope not to hit too often. 573 buf = append(buf, `time.Location(`...) 574 buf = append(buf, []byte(quote(loc.name))...) 575 buf = append(buf, `)`...) 576 } 577 buf = append(buf, ')') 578 return string(buf) 579 } 580 581 // Format returns a textual representation of the time value formatted according 582 // to the layout defined by the argument. See the documentation for the 583 // constant called Layout to see how to represent the layout format. 584 // 585 // The executable example for Time.Format demonstrates the working 586 // of the layout string in detail and is a good reference. 587 func (t Time) Format(layout string) string { 588 const bufSize = 64 589 var b []byte 590 max := len(layout) + 10 591 if max < bufSize { 592 var buf [bufSize]byte 593 b = buf[:0] 594 } else { 595 b = make([]byte, 0, max) 596 } 597 b = t.AppendFormat(b, layout) 598 return string(b) 599 } 600 601 // AppendFormat is like Format but appends the textual 602 // representation to b and returns the extended buffer. 603 func (t Time) AppendFormat(b []byte, layout string) []byte { 604 var ( 605 name, offset, abs = t.locabs() 606 607 year int = -1 608 month Month 609 day int 610 yday int 611 hour int = -1 612 min int 613 sec int 614 ) 615 // Each iteration generates one std value. 616 for layout != "" { 617 prefix, std, suffix := nextStdChunk(layout) 618 if prefix != "" { 619 b = append(b, prefix...) 620 } 621 if std == 0 { 622 break 623 } 624 layout = suffix 625 626 // Compute year, month, day if needed. 627 if year < 0 && std&stdNeedDate != 0 { 628 year, month, day, yday = absDate(abs, true) 629 yday++ 630 } 631 632 // Compute hour, minute, second if needed. 633 if hour < 0 && std&stdNeedClock != 0 { 634 hour, min, sec = absClock(abs) 635 } 636 637 switch std & stdMask { 638 case stdYear: 639 y := year 640 if y < 0 { 641 y = -y 642 } 643 b = appendInt(b, y%100, 2) 644 case stdLongYear: 645 b = appendInt(b, year, 4) 646 case stdMonth: 647 b = append(b, month.String()[:3]...) 648 case stdLongMonth: 649 m := month.String() 650 b = append(b, m...) 651 case stdNumMonth: 652 b = appendInt(b, int(month), 0) 653 case stdZeroMonth: 654 b = appendInt(b, int(month), 2) 655 case stdWeekDay: 656 b = append(b, absWeekday(abs).String()[:3]...) 657 case stdLongWeekDay: 658 s := absWeekday(abs).String() 659 b = append(b, s...) 660 case stdDay: 661 b = appendInt(b, day, 0) 662 case stdUnderDay: 663 if day < 10 { 664 b = append(b, ' ') 665 } 666 b = appendInt(b, day, 0) 667 case stdZeroDay: 668 b = appendInt(b, day, 2) 669 case stdUnderYearDay: 670 if yday < 100 { 671 b = append(b, ' ') 672 if yday < 10 { 673 b = append(b, ' ') 674 } 675 } 676 b = appendInt(b, yday, 0) 677 case stdZeroYearDay: 678 b = appendInt(b, yday, 3) 679 case stdHour: 680 b = appendInt(b, hour, 2) 681 case stdHour12: 682 // Noon is 12PM, midnight is 12AM. 683 hr := hour % 12 684 if hr == 0 { 685 hr = 12 686 } 687 b = appendInt(b, hr, 0) 688 case stdZeroHour12: 689 // Noon is 12PM, midnight is 12AM. 690 hr := hour % 12 691 if hr == 0 { 692 hr = 12 693 } 694 b = appendInt(b, hr, 2) 695 case stdMinute: 696 b = appendInt(b, min, 0) 697 case stdZeroMinute: 698 b = appendInt(b, min, 2) 699 case stdSecond: 700 b = appendInt(b, sec, 0) 701 case stdZeroSecond: 702 b = appendInt(b, sec, 2) 703 case stdPM: 704 if hour >= 12 { 705 b = append(b, "PM"...) 706 } else { 707 b = append(b, "AM"...) 708 } 709 case stdpm: 710 if hour >= 12 { 711 b = append(b, "pm"...) 712 } else { 713 b = append(b, "am"...) 714 } 715 case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ: 716 // Ugly special case. We cheat and take the "Z" variants 717 // to mean "the time zone as formatted for ISO 8601". 718 if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) { 719 b = append(b, 'Z') 720 break 721 } 722 zone := offset / 60 // convert to minutes 723 absoffset := offset 724 if zone < 0 { 725 b = append(b, '-') 726 zone = -zone 727 absoffset = -absoffset 728 } else { 729 b = append(b, '+') 730 } 731 b = appendInt(b, zone/60, 2) 732 if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ { 733 b = append(b, ':') 734 } 735 if std != stdNumShortTZ && std != stdISO8601ShortTZ { 736 b = appendInt(b, zone%60, 2) 737 } 738 739 // append seconds if appropriate 740 if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { 741 if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { 742 b = append(b, ':') 743 } 744 b = appendInt(b, absoffset%60, 2) 745 } 746 747 case stdTZ: 748 if name != "" { 749 b = append(b, name...) 750 break 751 } 752 // No time zone known for this time, but we must print one. 753 // Use the -0700 format. 754 zone := offset / 60 // convert to minutes 755 if zone < 0 { 756 b = append(b, '-') 757 zone = -zone 758 } else { 759 b = append(b, '+') 760 } 761 b = appendInt(b, zone/60, 2) 762 b = appendInt(b, zone%60, 2) 763 case stdFracSecond0, stdFracSecond9: 764 b = formatNano(b, uint(t.Nanosecond()), std) 765 } 766 } 767 return b 768 } 769 770 var errBad = errors.New("bad value for field") // placeholder not passed to user 771 772 // ParseError describes a problem parsing a time string. 773 type ParseError struct { 774 Layout string 775 Value string 776 LayoutElem string 777 ValueElem string 778 Message string 779 } 780 781 // These are borrowed from unicode/utf8 and strconv and replicate behavior in 782 // that package, since we can't take a dependency on either. 783 const ( 784 lowerhex = "0123456789abcdef" 785 runeSelf = 0x80 786 runeError = '\uFFFD' 787 ) 788 789 func quote(s string) string { 790 buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes 791 buf[0] = '"' 792 for i, c := range s { 793 if c >= runeSelf || c < ' ' { 794 // This means you are asking us to parse a time.Duration or 795 // time.Location with unprintable or non-ASCII characters in it. 796 // We don't expect to hit this case very often. We could try to 797 // reproduce strconv.Quote's behavior with full fidelity but 798 // given how rarely we expect to hit these edge cases, speed and 799 // conciseness are better. 800 var width int 801 if c == runeError { 802 width = 1 803 if i+2 < len(s) && s[i:i+3] == string(runeError) { 804 width = 3 805 } 806 } else { 807 width = len(string(c)) 808 } 809 for j := 0; j < width; j++ { 810 buf = append(buf, `\x`...) 811 buf = append(buf, lowerhex[s[i+j]>>4]) 812 buf = append(buf, lowerhex[s[i+j]&0xF]) 813 } 814 } else { 815 if c == '"' || c == '\\' { 816 buf = append(buf, '\\') 817 } 818 buf = append(buf, string(c)...) 819 } 820 } 821 buf = append(buf, '"') 822 return string(buf) 823 } 824 825 // Error returns the string representation of a ParseError. 826 func (e *ParseError) Error() string { 827 if e.Message == "" { 828 return "parsing time " + 829 quote(e.Value) + " as " + 830 quote(e.Layout) + ": cannot parse " + 831 quote(e.ValueElem) + " as " + 832 quote(e.LayoutElem) 833 } 834 return "parsing time " + 835 quote(e.Value) + e.Message 836 } 837 838 // isDigit reports whether s[i] is in range and is a decimal digit. 839 func isDigit(s string, i int) bool { 840 if len(s) <= i { 841 return false 842 } 843 c := s[i] 844 return '0' <= c && c <= '9' 845 } 846 847 // getnum parses s[0:1] or s[0:2] (fixed forces s[0:2]) 848 // as a decimal integer and returns the integer and the 849 // remainder of the string. 850 func getnum(s string, fixed bool) (int, string, error) { 851 if !isDigit(s, 0) { 852 return 0, s, errBad 853 } 854 if !isDigit(s, 1) { 855 if fixed { 856 return 0, s, errBad 857 } 858 return int(s[0] - '0'), s[1:], nil 859 } 860 return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil 861 } 862 863 // getnum3 parses s[0:1], s[0:2], or s[0:3] (fixed forces s[0:3]) 864 // as a decimal integer and returns the integer and the remainder 865 // of the string. 866 func getnum3(s string, fixed bool) (int, string, error) { 867 var n, i int 868 for i = 0; i < 3 && isDigit(s, i); i++ { 869 n = n*10 + int(s[i]-'0') 870 } 871 if i == 0 || fixed && i != 3 { 872 return 0, s, errBad 873 } 874 return n, s[i:], nil 875 } 876 877 func cutspace(s string) string { 878 for len(s) > 0 && s[0] == ' ' { 879 s = s[1:] 880 } 881 return s 882 } 883 884 // skip removes the given prefix from value, 885 // treating runs of space characters as equivalent. 886 func skip(value, prefix string) (string, error) { 887 for len(prefix) > 0 { 888 if prefix[0] == ' ' { 889 if len(value) > 0 && value[0] != ' ' { 890 return value, errBad 891 } 892 prefix = cutspace(prefix) 893 value = cutspace(value) 894 continue 895 } 896 if len(value) == 0 || value[0] != prefix[0] { 897 return value, errBad 898 } 899 prefix = prefix[1:] 900 value = value[1:] 901 } 902 return value, nil 903 } 904 905 // Parse parses a formatted string and returns the time value it represents. 906 // See the documentation for the constant called Layout to see how to 907 // represent the format. The second argument must be parseable using 908 // the format string (layout) provided as the first argument. 909 // 910 // The example for Time.Format demonstrates the working of the layout string 911 // in detail and is a good reference. 912 // 913 // When parsing (only), the input may contain a fractional second 914 // field immediately after the seconds field, even if the layout does not 915 // signify its presence. In that case either a comma or a decimal point 916 // followed by a maximal series of digits is parsed as a fractional second. 917 // 918 // Elements omitted from the layout are assumed to be zero or, when 919 // zero is impossible, one, so parsing "3:04pm" returns the time 920 // corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is 921 // 0, this time is before the zero Time). 922 // Years must be in the range 0000..9999. The day of the week is checked 923 // for syntax but it is otherwise ignored. 924 // 925 // For layouts specifying the two-digit year 06, a value NN >= 69 will be treated 926 // as 19NN and a value NN < 69 will be treated as 20NN. 927 // 928 // The remainder of this comment describes the handling of time zones. 929 // 930 // In the absence of a time zone indicator, Parse returns a time in UTC. 931 // 932 // When parsing a time with a zone offset like -0700, if the offset corresponds 933 // to a time zone used by the current location (Local), then Parse uses that 934 // location and zone in the returned time. Otherwise it records the time as 935 // being in a fabricated location with time fixed at the given zone offset. 936 // 937 // When parsing a time with a zone abbreviation like MST, if the zone abbreviation 938 // has a defined offset in the current location, then that offset is used. 939 // The zone abbreviation "UTC" is recognized as UTC regardless of location. 940 // If the zone abbreviation is unknown, Parse records the time as being 941 // in a fabricated location with the given zone abbreviation and a zero offset. 942 // This choice means that such a time can be parsed and reformatted with the 943 // same layout losslessly, but the exact instant used in the representation will 944 // differ by the actual zone offset. To avoid such problems, prefer time layouts 945 // that use a numeric zone offset, or use ParseInLocation. 946 func Parse(layout, value string) (Time, error) { 947 return parse(layout, value, UTC, Local) 948 } 949 950 // ParseInLocation is like Parse but differs in two important ways. 951 // First, in the absence of time zone information, Parse interprets a time as UTC; 952 // ParseInLocation interprets the time as in the given location. 953 // Second, when given a zone offset or abbreviation, Parse tries to match it 954 // against the Local location; ParseInLocation uses the given location. 955 func ParseInLocation(layout, value string, loc *Location) (Time, error) { 956 return parse(layout, value, loc, loc) 957 } 958 959 func parse(layout, value string, defaultLocation, local *Location) (Time, error) { 960 alayout, avalue := layout, value 961 rangeErrString := "" // set if a value is out of range 962 amSet := false // do we need to subtract 12 from the hour for midnight? 963 pmSet := false // do we need to add 12 to the hour? 964 965 // Time being constructed. 966 var ( 967 year int 968 month int = -1 969 day int = -1 970 yday int = -1 971 hour int 972 min int 973 sec int 974 nsec int 975 z *Location 976 zoneOffset int = -1 977 zoneName string 978 ) 979 980 // Each iteration processes one std value. 981 for { 982 var err error 983 prefix, std, suffix := nextStdChunk(layout) 984 stdstr := layout[len(prefix) : len(layout)-len(suffix)] 985 value, err = skip(value, prefix) 986 if err != nil { 987 return Time{}, &ParseError{alayout, avalue, prefix, value, ""} 988 } 989 if std == 0 { 990 if len(value) != 0 { 991 return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + quote(value)} 992 } 993 break 994 } 995 layout = suffix 996 var p string 997 switch std & stdMask { 998 case stdYear: 999 if len(value) < 2 { 1000 err = errBad 1001 break 1002 } 1003 hold := value 1004 p, value = value[0:2], value[2:] 1005 year, err = atoi(p) 1006 if err != nil { 1007 value = hold 1008 } else if year >= 69 { // Unix time starts Dec 31 1969 in some time zones 1009 year += 1900 1010 } else { 1011 year += 2000 1012 } 1013 case stdLongYear: 1014 if len(value) < 4 || !isDigit(value, 0) { 1015 err = errBad 1016 break 1017 } 1018 p, value = value[0:4], value[4:] 1019 year, err = atoi(p) 1020 case stdMonth: 1021 month, value, err = lookup(shortMonthNames, value) 1022 month++ 1023 case stdLongMonth: 1024 month, value, err = lookup(longMonthNames, value) 1025 month++ 1026 case stdNumMonth, stdZeroMonth: 1027 month, value, err = getnum(value, std == stdZeroMonth) 1028 if err == nil && (month <= 0 || 12 < month) { 1029 rangeErrString = "month" 1030 } 1031 case stdWeekDay: 1032 // Ignore weekday except for error checking. 1033 _, value, err = lookup(shortDayNames, value) 1034 case stdLongWeekDay: 1035 _, value, err = lookup(longDayNames, value) 1036 case stdDay, stdUnderDay, stdZeroDay: 1037 if std == stdUnderDay && len(value) > 0 && value[0] == ' ' { 1038 value = value[1:] 1039 } 1040 day, value, err = getnum(value, std == stdZeroDay) 1041 // Note that we allow any one- or two-digit day here. 1042 // The month, day, year combination is validated after we've completed parsing. 1043 case stdUnderYearDay, stdZeroYearDay: 1044 for i := 0; i < 2; i++ { 1045 if std == stdUnderYearDay && len(value) > 0 && value[0] == ' ' { 1046 value = value[1:] 1047 } 1048 } 1049 yday, value, err = getnum3(value, std == stdZeroYearDay) 1050 // Note that we allow any one-, two-, or three-digit year-day here. 1051 // The year-day, year combination is validated after we've completed parsing. 1052 case stdHour: 1053 hour, value, err = getnum(value, false) 1054 if hour < 0 || 24 <= hour { 1055 rangeErrString = "hour" 1056 } 1057 case stdHour12, stdZeroHour12: 1058 hour, value, err = getnum(value, std == stdZeroHour12) 1059 if hour < 0 || 12 < hour { 1060 rangeErrString = "hour" 1061 } 1062 case stdMinute, stdZeroMinute: 1063 min, value, err = getnum(value, std == stdZeroMinute) 1064 if min < 0 || 60 <= min { 1065 rangeErrString = "minute" 1066 } 1067 case stdSecond, stdZeroSecond: 1068 sec, value, err = getnum(value, std == stdZeroSecond) 1069 if sec < 0 || 60 <= sec { 1070 rangeErrString = "second" 1071 break 1072 } 1073 // Special case: do we have a fractional second but no 1074 // fractional second in the format? 1075 if len(value) >= 2 && commaOrPeriod(value[0]) && isDigit(value, 1) { 1076 _, std, _ = nextStdChunk(layout) 1077 std &= stdMask 1078 if std == stdFracSecond0 || std == stdFracSecond9 { 1079 // Fractional second in the layout; proceed normally 1080 break 1081 } 1082 // No fractional second in the layout but we have one in the input. 1083 n := 2 1084 for ; n < len(value) && isDigit(value, n); n++ { 1085 } 1086 nsec, rangeErrString, err = parseNanoseconds(value, n) 1087 value = value[n:] 1088 } 1089 case stdPM: 1090 if len(value) < 2 { 1091 err = errBad 1092 break 1093 } 1094 p, value = value[0:2], value[2:] 1095 switch p { 1096 case "PM": 1097 pmSet = true 1098 case "AM": 1099 amSet = true 1100 default: 1101 err = errBad 1102 } 1103 case stdpm: 1104 if len(value) < 2 { 1105 err = errBad 1106 break 1107 } 1108 p, value = value[0:2], value[2:] 1109 switch p { 1110 case "pm": 1111 pmSet = true 1112 case "am": 1113 amSet = true 1114 default: 1115 err = errBad 1116 } 1117 case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ: 1118 if (std == stdISO8601TZ || std == stdISO8601ShortTZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' { 1119 value = value[1:] 1120 z = UTC 1121 break 1122 } 1123 var sign, hour, min, seconds string 1124 if std == stdISO8601ColonTZ || std == stdNumColonTZ { 1125 if len(value) < 6 { 1126 err = errBad 1127 break 1128 } 1129 if value[3] != ':' { 1130 err = errBad 1131 break 1132 } 1133 sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:] 1134 } else if std == stdNumShortTZ || std == stdISO8601ShortTZ { 1135 if len(value) < 3 { 1136 err = errBad 1137 break 1138 } 1139 sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:] 1140 } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ { 1141 if len(value) < 9 { 1142 err = errBad 1143 break 1144 } 1145 if value[3] != ':' || value[6] != ':' { 1146 err = errBad 1147 break 1148 } 1149 sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:] 1150 } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz { 1151 if len(value) < 7 { 1152 err = errBad 1153 break 1154 } 1155 sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:] 1156 } else { 1157 if len(value) < 5 { 1158 err = errBad 1159 break 1160 } 1161 sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:] 1162 } 1163 var hr, mm, ss int 1164 hr, err = atoi(hour) 1165 if err == nil { 1166 mm, err = atoi(min) 1167 } 1168 if err == nil { 1169 ss, err = atoi(seconds) 1170 } 1171 zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds 1172 switch sign[0] { 1173 case '+': 1174 case '-': 1175 zoneOffset = -zoneOffset 1176 default: 1177 err = errBad 1178 } 1179 case stdTZ: 1180 // Does it look like a time zone? 1181 if len(value) >= 3 && value[0:3] == "UTC" { 1182 z = UTC 1183 value = value[3:] 1184 break 1185 } 1186 n, ok := parseTimeZone(value) 1187 if !ok { 1188 err = errBad 1189 break 1190 } 1191 zoneName, value = value[:n], value[n:] 1192 1193 case stdFracSecond0: 1194 // stdFracSecond0 requires the exact number of digits as specified in 1195 // the layout. 1196 ndigit := 1 + digitsLen(std) 1197 if len(value) < ndigit { 1198 err = errBad 1199 break 1200 } 1201 nsec, rangeErrString, err = parseNanoseconds(value, ndigit) 1202 value = value[ndigit:] 1203 1204 case stdFracSecond9: 1205 if len(value) < 2 || !commaOrPeriod(value[0]) || value[1] < '0' || '9' < value[1] { 1206 // Fractional second omitted. 1207 break 1208 } 1209 // Take any number of digits, even more than asked for, 1210 // because it is what the stdSecond case would do. 1211 i := 0 1212 for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' { 1213 i++ 1214 } 1215 nsec, rangeErrString, err = parseNanoseconds(value, 1+i) 1216 value = value[1+i:] 1217 } 1218 if rangeErrString != "" { 1219 return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"} 1220 } 1221 if err != nil { 1222 return Time{}, &ParseError{alayout, avalue, stdstr, value, ""} 1223 } 1224 } 1225 if pmSet && hour < 12 { 1226 hour += 12 1227 } else if amSet && hour == 12 { 1228 hour = 0 1229 } 1230 1231 // Convert yday to day, month. 1232 if yday >= 0 { 1233 var d int 1234 var m int 1235 if isLeap(year) { 1236 if yday == 31+29 { 1237 m = int(February) 1238 d = 29 1239 } else if yday > 31+29 { 1240 yday-- 1241 } 1242 } 1243 if yday < 1 || yday > 365 { 1244 return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year out of range"} 1245 } 1246 if m == 0 { 1247 m = (yday-1)/31 + 1 1248 if int(daysBefore[m]) < yday { 1249 m++ 1250 } 1251 d = yday - int(daysBefore[m-1]) 1252 } 1253 // If month, day already seen, yday's m, d must match. 1254 // Otherwise, set them from m, d. 1255 if month >= 0 && month != m { 1256 return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year does not match month"} 1257 } 1258 month = m 1259 if day >= 0 && day != d { 1260 return Time{}, &ParseError{alayout, avalue, "", value, ": day-of-year does not match day"} 1261 } 1262 day = d 1263 } else { 1264 if month < 0 { 1265 month = int(January) 1266 } 1267 if day < 0 { 1268 day = 1 1269 } 1270 } 1271 1272 // Validate the day of the month. 1273 if day < 1 || day > daysIn(Month(month), year) { 1274 return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"} 1275 } 1276 1277 if z != nil { 1278 return Date(year, Month(month), day, hour, min, sec, nsec, z), nil 1279 } 1280 1281 if zoneOffset != -1 { 1282 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC) 1283 t.addSec(-int64(zoneOffset)) 1284 1285 // Look for local zone with the given offset. 1286 // If that zone was in effect at the given time, use it. 1287 name, offset, _, _, _ := local.lookup(t.unixSec()) 1288 if offset == zoneOffset && (zoneName == "" || name == zoneName) { 1289 t.setLoc(local) 1290 return t, nil 1291 } 1292 1293 // Otherwise create fake zone to record offset. 1294 t.setLoc(FixedZone(zoneName, zoneOffset)) 1295 return t, nil 1296 } 1297 1298 if zoneName != "" { 1299 t := Date(year, Month(month), day, hour, min, sec, nsec, UTC) 1300 // Look for local zone with the given offset. 1301 // If that zone was in effect at the given time, use it. 1302 offset, ok := local.lookupName(zoneName, t.unixSec()) 1303 if ok { 1304 t.addSec(-int64(offset)) 1305 t.setLoc(local) 1306 return t, nil 1307 } 1308 1309 // Otherwise, create fake zone with unknown offset. 1310 if len(zoneName) > 3 && zoneName[:3] == "GMT" { 1311 offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT. 1312 offset *= 3600 1313 } 1314 t.setLoc(FixedZone(zoneName, offset)) 1315 return t, nil 1316 } 1317 1318 // Otherwise, fall back to default. 1319 return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil 1320 } 1321 1322 // parseTimeZone parses a time zone string and returns its length. Time zones 1323 // are human-generated and unpredictable. We can't do precise error checking. 1324 // On the other hand, for a correct parse there must be a time zone at the 1325 // beginning of the string, so it's almost always true that there's one 1326 // there. We look at the beginning of the string for a run of upper-case letters. 1327 // If there are more than 5, it's an error. 1328 // If there are 4 or 5 and the last is a T, it's a time zone. 1329 // If there are 3, it's a time zone. 1330 // Otherwise, other than special cases, it's not a time zone. 1331 // GMT is special because it can have an hour offset. 1332 func parseTimeZone(value string) (length int, ok bool) { 1333 if len(value) < 3 { 1334 return 0, false 1335 } 1336 // Special case 1: ChST and MeST are the only zones with a lower-case letter. 1337 if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") { 1338 return 4, true 1339 } 1340 // Special case 2: GMT may have an hour offset; treat it specially. 1341 if value[:3] == "GMT" { 1342 length = parseGMT(value) 1343 return length, true 1344 } 1345 // Special Case 3: Some time zones are not named, but have +/-00 format 1346 if value[0] == '+' || value[0] == '-' { 1347 length = parseSignedOffset(value) 1348 ok := length > 0 // parseSignedOffset returns 0 in case of bad input 1349 return length, ok 1350 } 1351 // How many upper-case letters are there? Need at least three, at most five. 1352 var nUpper int 1353 for nUpper = 0; nUpper < 6; nUpper++ { 1354 if nUpper >= len(value) { 1355 break 1356 } 1357 if c := value[nUpper]; c < 'A' || 'Z' < c { 1358 break 1359 } 1360 } 1361 switch nUpper { 1362 case 0, 1, 2, 6: 1363 return 0, false 1364 case 5: // Must end in T to match. 1365 if value[4] == 'T' { 1366 return 5, true 1367 } 1368 case 4: 1369 // Must end in T, except one special case. 1370 if value[3] == 'T' || value[:4] == "WITA" { 1371 return 4, true 1372 } 1373 case 3: 1374 return 3, true 1375 } 1376 return 0, false 1377 } 1378 1379 // parseGMT parses a GMT time zone. The input string is known to start "GMT". 1380 // The function checks whether that is followed by a sign and a number in the 1381 // range -23 through +23 excluding zero. 1382 func parseGMT(value string) int { 1383 value = value[3:] 1384 if len(value) == 0 { 1385 return 3 1386 } 1387 1388 return 3 + parseSignedOffset(value) 1389 } 1390 1391 // parseSignedOffset parses a signed timezone offset (e.g. "+03" or "-04"). 1392 // The function checks for a signed number in the range -23 through +23 excluding zero. 1393 // Returns length of the found offset string or 0 otherwise 1394 func parseSignedOffset(value string) int { 1395 sign := value[0] 1396 if sign != '-' && sign != '+' { 1397 return 0 1398 } 1399 x, rem, err := leadingInt(value[1:]) 1400 1401 // fail if nothing consumed by leadingInt 1402 if err != nil || value[1:] == rem { 1403 return 0 1404 } 1405 if x > 23 { 1406 return 0 1407 } 1408 return len(value) - len(rem) 1409 } 1410 1411 func commaOrPeriod(b byte) bool { 1412 return b == '.' || b == ',' 1413 } 1414 1415 func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) { 1416 if !commaOrPeriod(value[0]) { 1417 err = errBad 1418 return 1419 } 1420 if nbytes > 10 { 1421 value = value[:10] 1422 nbytes = 10 1423 } 1424 if ns, err = atoi(value[1:nbytes]); err != nil { 1425 return 1426 } 1427 if ns < 0 { 1428 rangeErrString = "fractional second" 1429 return 1430 } 1431 // We need nanoseconds, which means scaling by the number 1432 // of missing digits in the format, maximum length 10. 1433 scaleDigits := 10 - nbytes 1434 for i := 0; i < scaleDigits; i++ { 1435 ns *= 10 1436 } 1437 return 1438 } 1439 1440 var errLeadingInt = errors.New("time: bad [0-9]*") // never printed 1441 1442 // leadingInt consumes the leading [0-9]* from s. 1443 func leadingInt(s string) (x uint64, rem string, err error) { 1444 i := 0 1445 for ; i < len(s); i++ { 1446 c := s[i] 1447 if c < '0' || c > '9' { 1448 break 1449 } 1450 if x > 1<<63/10 { 1451 // overflow 1452 return 0, "", errLeadingInt 1453 } 1454 x = x*10 + uint64(c) - '0' 1455 if x > 1<<63 { 1456 // overflow 1457 return 0, "", errLeadingInt 1458 } 1459 } 1460 return x, s[i:], nil 1461 } 1462 1463 // leadingFraction consumes the leading [0-9]* from s. 1464 // It is used only for fractions, so does not return an error on overflow, 1465 // it just stops accumulating precision. 1466 func leadingFraction(s string) (x uint64, scale float64, rem string) { 1467 i := 0 1468 scale = 1 1469 overflow := false 1470 for ; i < len(s); i++ { 1471 c := s[i] 1472 if c < '0' || c > '9' { 1473 break 1474 } 1475 if overflow { 1476 continue 1477 } 1478 if x > (1<<63-1)/10 { 1479 // It's possible for overflow to give a positive number, so take care. 1480 overflow = true 1481 continue 1482 } 1483 y := x*10 + uint64(c) - '0' 1484 if y > 1<<63 { 1485 overflow = true 1486 continue 1487 } 1488 x = y 1489 scale *= 10 1490 } 1491 return x, scale, s[i:] 1492 } 1493 1494 var unitMap = map[string]uint64{ 1495 "ns": uint64(Nanosecond), 1496 "us": uint64(Microsecond), 1497 "µs": uint64(Microsecond), // U+00B5 = micro symbol 1498 "μs": uint64(Microsecond), // U+03BC = Greek letter mu 1499 "ms": uint64(Millisecond), 1500 "s": uint64(Second), 1501 "m": uint64(Minute), 1502 "h": uint64(Hour), 1503 } 1504 1505 // ParseDuration parses a duration string. 1506 // A duration string is a possibly signed sequence of 1507 // decimal numbers, each with optional fraction and a unit suffix, 1508 // such as "300ms", "-1.5h" or "2h45m". 1509 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". 1510 func ParseDuration(s string) (Duration, error) { 1511 // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ 1512 orig := s 1513 var d uint64 1514 neg := false 1515 1516 // Consume [-+]? 1517 if s != "" { 1518 c := s[0] 1519 if c == '-' || c == '+' { 1520 neg = c == '-' 1521 s = s[1:] 1522 } 1523 } 1524 // Special case: if all that is left is "0", this is zero. 1525 if s == "0" { 1526 return 0, nil 1527 } 1528 if s == "" { 1529 return 0, errors.New("time: invalid duration " + quote(orig)) 1530 } 1531 for s != "" { 1532 var ( 1533 v, f uint64 // integers before, after decimal point 1534 scale float64 = 1 // value = v + f/scale 1535 ) 1536 1537 var err error 1538 1539 // The next character must be [0-9.] 1540 if !(s[0] == '.' || '0' <= s[0] && s[0] <= '9') { 1541 return 0, errors.New("time: invalid duration " + quote(orig)) 1542 } 1543 // Consume [0-9]* 1544 pl := len(s) 1545 v, s, err = leadingInt(s) 1546 if err != nil { 1547 return 0, errors.New("time: invalid duration " + quote(orig)) 1548 } 1549 pre := pl != len(s) // whether we consumed anything before a period 1550 1551 // Consume (\.[0-9]*)? 1552 post := false 1553 if s != "" && s[0] == '.' { 1554 s = s[1:] 1555 pl := len(s) 1556 f, scale, s = leadingFraction(s) 1557 post = pl != len(s) 1558 } 1559 if !pre && !post { 1560 // no digits (e.g. ".s" or "-.s") 1561 return 0, errors.New("time: invalid duration " + quote(orig)) 1562 } 1563 1564 // Consume unit. 1565 i := 0 1566 for ; i < len(s); i++ { 1567 c := s[i] 1568 if c == '.' || '0' <= c && c <= '9' { 1569 break 1570 } 1571 } 1572 if i == 0 { 1573 return 0, errors.New("time: missing unit in duration " + quote(orig)) 1574 } 1575 u := s[:i] 1576 s = s[i:] 1577 unit, ok := unitMap[u] 1578 if !ok { 1579 return 0, errors.New("time: unknown unit " + quote(u) + " in duration " + quote(orig)) 1580 } 1581 if v > 1<<63/unit { 1582 // overflow 1583 return 0, errors.New("time: invalid duration " + quote(orig)) 1584 } 1585 v *= unit 1586 if f > 0 { 1587 // float64 is needed to be nanosecond accurate for fractions of hours. 1588 // v >= 0 && (f*unit/scale) <= 3.6e+12 (ns/h, h is the largest unit) 1589 v += uint64(float64(f) * (float64(unit) / scale)) 1590 if v > 1<<63 { 1591 // overflow 1592 return 0, errors.New("time: invalid duration " + quote(orig)) 1593 } 1594 } 1595 d += v 1596 if d > 1<<63 { 1597 return 0, errors.New("time: invalid duration " + quote(orig)) 1598 } 1599 } 1600 if neg { 1601 return -Duration(d), nil 1602 } 1603 if d > 1<<63-1 { 1604 return 0, errors.New("time: invalid duration " + quote(orig)) 1605 } 1606 return Duration(d), nil 1607 }