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