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