- The Go Programming Language (original) (raw)

Source file src/time/format.go

 1  
 2  
 3  
 4  
 5  package time
 6  
 7  import (
 8  	"errors"
 9  	"internal/stringslite"
10  	_ "unsafe" 
11  )
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  

100   101   102   103   104   105   106   107   108   109  const ( 110   Layout = "01/02 03:04:05PM '06 -0700" 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" 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" 119   RFC3339 = "2006-01-02T15:04:05Z07:00" 120   RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" 121   Kitchen = "3:04PM" 122   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   132  const ( 133   _ = iota 134   stdLongMonth = iota + stdNeedDate
135   stdMonth
136   stdNumMonth
137   stdZeroMonth
138   stdLongWeekDay
139   stdWeekDay
140   stdDay
141   stdUnderDay
142   stdZeroDay
143   stdUnderYearDay = iota + stdNeedYday
144   stdZeroYearDay
145   stdHour = iota + stdNeedClock 146   stdHour12
147   stdZeroHour12
148   stdMinute
149   stdZeroMinute
150   stdSecond
151   stdZeroSecond
152   stdLongYear = iota + stdNeedDate
153   stdYear
154   stdPM = iota + stdNeedClock 155   stdpm
156   stdTZ = iota
157   stdISO8601TZ
158   stdISO8601SecondsTZ
159   stdISO8601ShortTZ
160   stdISO8601ColonTZ
161   stdISO8601ColonSecondsTZ
162   stdNumTZ
163   stdNumSecondsTz
164   stdNumShortTZ
165   stdNumColonTZ
166   stdNumColonSecondsTZ
167   stdFracSecond0
168   stdFracSecond9
169   170   stdNeedDate = 1 << 8
171   stdNeedYday = 1 << 9
172   stdNeedClock = 1 << 10
173   stdArgShift = 16
174   stdSeparatorShift = 28
175   stdMask = 1<<stdArgShift - 1 176  ) 177   178   179  var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear} 180   181   182   183  func startsWithLowerCase(str string) bool { 184   if len(str) == 0 { 185   return false 186   } 187   c := str[0] 188   return 'a' <= c && c <= 'z' 189  } 190   191   192   193   194   195   196   197   198   199   200   201   202   203  func nextStdChunk(layout string) (prefix string, std int, suffix string) { 204   for i := 0; i < len(layout); i++ { 205   switch c := int(layout[i]); c { 206   case 'J': 207   if len(layout) >= i+3 && layout[i:i+3] == "Jan" { 208   if len(layout) >= i+7 && layout[i:i+7] == "January" { 209   return layout[0:i], stdLongMonth, layout[i+7:] 210   } 211   if !startsWithLowerCase(layout[i+3:]) { 212   return layout[0:i], stdMonth, layout[i+3:] 213   } 214   } 215   216   case 'M': 217   if len(layout) >= i+3 { 218   if layout[i:i+3] == "Mon" { 219   if len(layout) >= i+6 && layout[i:i+6] == "Monday" { 220   return layout[0:i], stdLongWeekDay, layout[i+6:] 221   } 222   if !startsWithLowerCase(layout[i+3:]) { 223   return layout[0:i], stdWeekDay, layout[i+3:] 224   } 225   } 226   if layout[i:i+3] == "MST" { 227   return layout[0:i], stdTZ, layout[i+3:] 228   } 229   } 230   231   case '0': 232   if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' { 233   return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:] 234   } 235   if len(layout) >= i+3 && layout[i+1] == '0' && layout[i+2] == '2' { 236   return layout[0:i], stdZeroYearDay, layout[i+3:] 237   } 238   239   case '1': 240   if len(layout) >= i+2 && layout[i+1] == '5' { 241   return layout[0:i], stdHour, layout[i+2:] 242   } 243   return layout[0:i], stdNumMonth, layout[i+1:] 244   245   case '2': 246   if len(layout) >= i+4 && layout[i:i+4] == "2006" { 247   return layout[0:i], stdLongYear, layout[i+4:] 248   } 249   return layout[0:i], stdDay, layout[i+1:] 250   251   case '
': 252   if len(layout) >= i+2 && layout[i+1] == '2' { 253   254   if len(layout) >= i+5 && layout[i+1:i+5] == "2006" { 255   return layout[0 : i+1], stdLongYear, layout[i+5:] 256   } 257   return layout[0:i], stdUnderDay, layout[i+2:] 258   } 259   if len(layout) >= i+3 && layout[i+1] == '
' && layout[i+2] == '2' { 260   return layout[0:i], stdUnderYearDay, layout[i+3:] 261   } 262   263   case '3': 264   return layout[0:i], stdHour12, layout[i+1:] 265   266   case '4': 267   return layout[0:i], stdMinute, layout[i+1:] 268   269   case '5': 270   return layout[0:i], stdSecond, layout[i+1:] 271   272   case 'P': 273   if len(layout) >= i+2 && layout[i+1] == 'M' { 274   return layout[0:i], stdPM, layout[i+2:] 275   } 276   277   case 'p': 278   if len(layout) >= i+2 && layout[i+1] == 'm' { 279   return layout[0:i], stdpm, layout[i+2:] 280   } 281   282   case '-': 283   if len(layout) >= i+7 && layout[i:i+7] == "-070000" { 284   return layout[0:i], stdNumSecondsTz, layout[i+7:] 285   } 286   if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" { 287   return layout[0:i], stdNumColonSecondsTZ, layout[i+9:] 288   } 289   if len(layout) >= i+5 && layout[i:i+5] == "-0700" { 290   return layout[0:i], stdNumTZ, layout[i+5:] 291   } 292   if len(layout) >= i+6 && layout[i:i+6] == "-07:00" { 293   return layout[0:i], stdNumColonTZ, layout[i+6:] 294   } 295   if len(layout) >= i+3 && layout[i:i+3] == "-07" { 296   return layout[0:i], stdNumShortTZ, layout[i+3:] 297   } 298   299   case 'Z': 300   if len(layout) >= i+7 && layout[i:i+7] == "Z070000" { 301   return layout[0:i], stdISO8601SecondsTZ, layout[i+7:] 302   } 303   if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" { 304   return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:] 305   } 306   if len(layout) >= i+5 && layout[i:i+5] == "Z0700" { 307   return layout[0:i], stdISO8601TZ, layout[i+5:] 308   } 309   if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" { 310   return layout[0:i], stdISO8601ColonTZ, layout[i+6:] 311   } 312   if len(layout) >= i+3 && layout[i:i+3] == "Z07" { 313   return layout[0:i], stdISO8601ShortTZ, layout[i+3:] 314   } 315   316   case '.', ',': 317   if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') { 318   ch := layout[i+1] 319   j := i + 1 320   for j < len(layout) && layout[j] == ch { 321   j++ 322   } 323   324   if !isDigit(layout, j) { 325   code := stdFracSecond0 326   if layout[i+1] == '9' { 327   code = stdFracSecond9 328   } 329   std := stdFracSecond(code, j-(i+1), c) 330   return layout[0:i], std, layout[j:] 331   } 332   } 333   } 334   } 335   return layout, 0, "" 336  } 337   338  var longDayNames = []string{ 339   "Sunday", 340   "Monday", 341   "Tuesday", 342   "Wednesday", 343   "Thursday", 344   "Friday", 345   "Saturday", 346  } 347   348  var shortDayNames = []string{ 349   "Sun", 350   "Mon", 351   "Tue", 352   "Wed", 353   "Thu", 354   "Fri", 355   "Sat", 356  } 357   358  var shortMonthNames = []string{ 359   "Jan", 360   "Feb", 361   "Mar", 362   "Apr", 363   "May", 364   "Jun", 365   "Jul", 366   "Aug", 367   "Sep", 368   "Oct", 369   "Nov", 370   "Dec", 371  } 372   373  var longMonthNames = []string{ 374   "January", 375   "February", 376   "March", 377   "April", 378   "May", 379   "June", 380   "July", 381   "August", 382   "September", 383   "October", 384   "November", 385   "December", 386  } 387   388   389   390  func match(s1, s2 string) bool { 391   for i := 0; i < len(s1); i++ { 392   c1 := s1[i] 393   c2 := s2[i] 394   if c1 != c2 { 395   396   c1 |= 'a' - 'A' 397   c2 |= 'a' - 'A' 398   if c1 != c2 || c1 < 'a' || c1 > 'z' { 399   return false 400   } 401   } 402   } 403   return true 404  } 405   406  func lookup(tab []string, val string) (int, string, error) { 407   for i, v := range tab { 408   if len(val) >= len(v) && match(val[:len(v)], v) { 409   return i, val[len(v):], nil 410   } 411   } 412   return -1, val, errBad 413  } 414   415   416   417   418  func appendInt(b []byte, x int, width int) []byte { 419   u := uint(x) 420   if x < 0 { 421   b = append(b, '-') 422   u = uint(-x) 423   } 424   425   426   utod := func(u uint) byte { return '0' + byte(u) } 427   switch { 428   case width == 2 && u < 1e2: 429   return append(b, utod(u/1e1), utod(u%1e1)) 430   case width == 4 && u < 1e4: 431   return append(b, utod(u/1e3), utod(u/1e2%1e1), utod(u/1e1%1e1), utod(u%1e1)) 432   } 433   434   435   var n int 436   if u == 0 { 437   n = 1 438   } 439   for u2 := u; u2 > 0; u2 /= 10 { 440   n++ 441   } 442   443   444   for pad := width - n; pad > 0; pad-- { 445   b = append(b, '0') 446   } 447   448   449   if len(b)+n <= cap(b) { 450   b = b[:len(b)+n] 451   } else { 452   b = append(b, make([]byte, n)...) 453   } 454   455   456   i := len(b) - 1 457   for u >= 10 && i > 0 { 458   q := u / 10 459   b[i] = utod(u - q*10) 460   u = q 461   i-- 462   } 463   b[i] = utod(u) 464   return b 465  } 466   467   468  var errAtoi = errors.New("time: invalid number") 469   470   471  func atoi[bytes []byte | string](s bytes) (x int, err error) { 472   neg := false 473   if len(s) > 0 && (s[0] == '-' || s[0] == '+') { 474   neg = s[0] == '-' 475   s = s[1:] 476   } 477   q, rem, err := leadingInt(s) 478   x = int(q) 479   if err != nil || len(rem) > 0 { 480   return 0, errAtoi 481   } 482   if neg { 483   x = -x 484   } 485   return x, nil 486  } 487   488   489   490   491  func stdFracSecond(code, n, c int) int { 492   493   if c == '.' { 494   return code | ((n & 0xfff) << stdArgShift) 495   } 496   return code | ((n & 0xfff) << stdArgShift) | 1<<stdSeparatorShift 497  } 498   499  func digitsLen(std int) int { 500   return (std >> stdArgShift) & 0xfff 501  } 502   503  func separator(std int) byte { 504   if (std >> stdSeparatorShift) == 0 { 505   return '.' 506   } 507   return ',' 508  } 509   510   511   512  func appendNano(b []byte, nanosec int, std int) []byte { 513   trim := std&stdMask == stdFracSecond9 514   n := digitsLen(std) 515   if trim && (n == 0 || nanosec == 0) { 516   return b 517   } 518   dot := separator(std) 519   b = append(b, dot) 520   b = appendInt(b, nanosec, 9) 521   if n < 9 { 522   b = b[:len(b)-9+n] 523   } 524   if trim { 525   for len(b) > 0 && b[len(b)-1] == '0' { 526   b = b[:len(b)-1] 527   } 528   if len(b) > 0 && b[len(b)-1] == dot { 529   b = b[:len(b)-1] 530   } 531   } 532   return b 533  } 534   535   536   537   538   539   540   541   542   543   544   545   546  func (t Time) String() string { 547   s := t.Format("2006-01-02 15:04:05.999999999 -0700 MST") 548   549   550   if t.wall&hasMonotonic != 0 { 551   m2 := uint64(t.ext) 552   sign := byte('+') 553   if t.ext < 0 { 554   sign = '-' 555   m2 = -m2 556   } 557   m1, m2 := m2/1e9, m2%1e9 558   m0, m1 := m1/1e9, m1%1e9 559   buf := make([]byte, 0, 24) 560   buf = append(buf, " m="...) 561   buf = append(buf, sign) 562   wid := 0 563   if m0 != 0 { 564   buf = appendInt(buf, int(m0), 0) 565   wid = 9 566   } 567   buf = appendInt(buf, int(m1), wid) 568   buf = append(buf, '.') 569   buf = appendInt(buf, int(m2), 9) 570   s += string(buf) 571   } 572   return s 573  } 574   575   576   577  func (t Time) GoString() string { 578   abs := t.absSec() 579   year, month, day := abs.days().date() 580   hour, minute, second := abs.clock() 581   582   buf := make([]byte, 0, len("time.Date(9999, time.September, 31, 23, 59, 59, 999999999, time.Local)")) 583   buf = append(buf, "time.Date("...) 584   buf = appendInt(buf, year, 0) 585   if January <= month && month <= December { 586   buf = append(buf, ", time."...) 587   buf = append(buf, longMonthNames[month-1]...) 588   } else { 589   590   591   buf = appendInt(buf, int(month), 0) 592   } 593   buf = append(buf, ", "...) 594   buf = appendInt(buf, day, 0) 595   buf = append(buf, ", "...) 596   buf = appendInt(buf, hour, 0) 597   buf = append(buf, ", "...) 598   buf = appendInt(buf, minute, 0) 599   buf = append(buf, ", "...) 600   buf = appendInt(buf, second, 0) 601   buf = append(buf, ", "...) 602   buf = appendInt(buf, t.Nanosecond(), 0) 603   buf = append(buf, ", "...) 604   switch loc := t.Location(); loc { 605   case UTC, nil: 606   buf = append(buf, "time.UTC"...) 607   case Local: 608   buf = append(buf, "time.Local"...) 609   default: 610   611   612   613   614   615   616   617   618   619   620   621   622   623   624   625   buf = append(buf, time.Location(...) 626   buf = append(buf, quote(loc.name)...) 627   buf = append(buf, ')') 628   } 629   buf = append(buf, ')') 630   return string(buf) 631  } 632   633   634   635   636   637   638   639  func (t Time) Format(layout string) string { 640   const bufSize = 64 641   var b []byte 642   max := len(layout) + 10 643   if max < bufSize { 644   var buf [bufSize]byte 645   b = buf[:0] 646   } else { 647   b = make([]byte, 0, max) 648   } 649   b = t.AppendFormat(b, layout) 650   return string(b) 651  } 652   653   654   655  func (t Time) AppendFormat(b []byte, layout string) []byte { 656   657   switch layout { 658   case RFC3339: 659   return t.appendFormatRFC3339(b, false) 660   case RFC3339Nano: 661   return t.appendFormatRFC3339(b, true) 662   default: 663   return t.appendFormat(b, layout) 664   } 665  } 666   667  func (t Time) appendFormat(b []byte, layout string) []byte { 668   name, offset, abs := t.locabs() 669   days := abs.days() 670   671   var ( 672   year int = -1 673   month Month 674   day int 675   yday int = -1 676   hour int = -1 677   min int 678   sec int 679   ) 680   681   682   for layout != "" { 683   prefix, std, suffix := nextStdChunk(layout) 684   if prefix != "" { 685   b = append(b, prefix...) 686   } 687   if std == 0 { 688   break 689   } 690   layout = suffix 691   692   693   if year < 0 && std&stdNeedDate != 0 { 694   year, month, day = days.date() 695   } 696   if yday < 0 && std&stdNeedYday != 0 { 697   _, yday = days.yearYday() 698   } 699   700   701   if hour < 0 && std&stdNeedClock != 0 { 702   hour, min, sec = abs.clock() 703   } 704   705   switch std & stdMask { 706   case stdYear: 707   y := year 708   if y < 0 { 709   y = -y 710   } 711   b = appendInt(b, y%100, 2) 712   case stdLongYear: 713   b = appendInt(b, year, 4) 714   case stdMonth: 715   b = append(b, month.String()[:3]...) 716   case stdLongMonth: 717   m := month.String() 718   b = append(b, m...) 719   case stdNumMonth: 720   b = appendInt(b, int(month), 0) 721   case stdZeroMonth: 722   b = appendInt(b, int(month), 2) 723   case stdWeekDay: 724   b = append(b, days.weekday().String()[:3]...) 725   case stdLongWeekDay: 726   s := days.weekday().String() 727   b = append(b, s...) 728   case stdDay: 729   b = appendInt(b, day, 0) 730   case stdUnderDay: 731   if day < 10 { 732   b = append(b, ' ') 733   } 734   b = appendInt(b, day, 0) 735   case stdZeroDay: 736   b = appendInt(b, day, 2) 737   case stdUnderYearDay: 738   if yday < 100 { 739   b = append(b, ' ') 740   if yday < 10 { 741   b = append(b, ' ') 742   } 743   } 744   b = appendInt(b, yday, 0) 745   case stdZeroYearDay: 746   b = appendInt(b, yday, 3) 747   case stdHour: 748   b = appendInt(b, hour, 2) 749   case stdHour12: 750   751   hr := hour % 12 752   if hr == 0 { 753   hr = 12 754   } 755   b = appendInt(b, hr, 0) 756   case stdZeroHour12: 757   758   hr := hour % 12 759   if hr == 0 { 760   hr = 12 761   } 762   b = appendInt(b, hr, 2) 763   case stdMinute: 764   b = appendInt(b, min, 0) 765   case stdZeroMinute: 766   b = appendInt(b, min, 2) 767   case stdSecond: 768   b = appendInt(b, sec, 0) 769   case stdZeroSecond: 770   b = appendInt(b, sec, 2) 771   case stdPM: 772   if hour >= 12 { 773   b = append(b, "PM"...) 774   } else { 775   b = append(b, "AM"...) 776   } 777   case stdpm: 778   if hour >= 12 { 779   b = append(b, "pm"...) 780   } else { 781   b = append(b, "am"...) 782   } 783   case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ: 784   785   786   if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) { 787   b = append(b, 'Z') 788   break 789   } 790   zone := offset / 60 791   absoffset := offset 792   if zone < 0 { 793   b = append(b, '-') 794   zone = -zone 795   absoffset = -absoffset 796   } else { 797   b = append(b, '+') 798   } 799   b = appendInt(b, zone/60, 2) 800   if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ { 801   b = append(b, ':') 802   } 803   if std != stdNumShortTZ && std != stdISO8601ShortTZ { 804   b = appendInt(b, zone%60, 2) 805   } 806   807   808   if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { 809   if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ { 810   b = append(b, ':') 811   } 812   b = appendInt(b, absoffset%60, 2) 813   } 814   815   case stdTZ: 816   if name != "" { 817   b = append(b, name...) 818   break 819   } 820   821   822   zone := offset / 60 823   if zone < 0 { 824   b = append(b, '-') 825   zone = -zone 826   } else { 827   b = append(b, '+') 828   } 829   b = appendInt(b, zone/60, 2) 830   b = appendInt(b, zone%60, 2) 831   case stdFracSecond0, stdFracSecond9: 832   b = appendNano(b, t.Nanosecond(), std) 833   } 834   } 835   return b 836  } 837   838  var errBad = errors.New("bad value for field") 839   840   841  type ParseError struct { 842   Layout string 843   Value string 844   LayoutElem string 845   ValueElem string 846   Message string 847  } 848   849   850   851  func newParseError(layout, value, layoutElem, valueElem, message string) *ParseError { 852   valueCopy := stringslite.Clone(value) 853   valueElemCopy := stringslite.Clone(valueElem) 854   return &ParseError{layout, valueCopy, layoutElem, valueElemCopy, message} 855  } 856   857   858   859  const ( 860   lowerhex = "0123456789abcdef" 861   runeSelf = 0x80 862   runeError = '\uFFFD' 863  ) 864   865  func quote(s string) string { 866   buf := make([]byte, 1, len(s)+2) 867   buf[0] = '"' 868   for i, c := range s { 869   if c >= runeSelf || c < ' ' { 870   871   872   873   874   875   876   var width int 877   if c == runeError { 878   width = 1 879   if i+2 < len(s) && s[i:i+3] == string(runeError) { 880   width = 3 881   } 882   } else { 883   width = len(string(c)) 884   } 885   for j := 0; j < width; j++ { 886   buf = append(buf, \x...) 887   buf = append(buf, lowerhex[s[i+j]>>4]) 888   buf = append(buf, lowerhex[s[i+j]&0xF]) 889   } 890   } else { 891   if c == '"' || c == '\' { 892   buf = append(buf, '\') 893   } 894   buf = append(buf, string(c)...) 895   } 896   } 897   buf = append(buf, '"') 898   return string(buf) 899  } 900   901   902  func (e *ParseError) Error() string { 903   if e.Message == "" { 904   return "parsing time " + 905   quote(e.Value) + " as " + 906   quote(e.Layout) + ": cannot parse " + 907   quote(e.ValueElem) + " as " + 908   quote(e.LayoutElem) 909   } 910   return "parsing time " + 911   quote(e.Value) + e.Message 912  } 913   914   915  func isDigit[bytes []byte | string](s bytes, i int) bool { 916   if len(s) <= i { 917   return false 918   } 919   c := s[i] 920   return '0' <= c && c <= '9' 921  } 922   923   924   925   926  func getnum(s string, fixed bool) (int, string, error) { 927   if !isDigit(s, 0) { 928   return 0, s, errBad 929   } 930   if !isDigit(s, 1) { 931   if fixed { 932   return 0, s, errBad 933   } 934   return int(s[0] - '0'), s[1:], nil 935   } 936   return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil 937  } 938   939   940   941   942  func getnum3(s string, fixed bool) (int, string, error) { 943   var n, i int 944   for i = 0; i < 3 && isDigit(s, i); i++ { 945   n = n*10 + int(s[i]-'0') 946   } 947   if i == 0 || fixed && i != 3 { 948   return 0, s, errBad 949   } 950   return n, s[i:], nil 951  } 952   953  func cutspace(s string) string { 954   for len(s) > 0 && s[0] == ' ' { 955   s = s[1:] 956   } 957   return s 958  } 959   960   961   962  func skip(value, prefix string) (string, error) { 963   for len(prefix) > 0 { 964   if prefix[0] == ' ' { 965   if len(value) > 0 && value[0] != ' ' { 966   return value, errBad 967   } 968   prefix = cutspace(prefix) 969   value = cutspace(value) 970   continue 971   } 972   if len(value) == 0 || value[0] != prefix[0] { 973   return value, errBad 974   } 975   prefix = prefix[1:] 976   value = value[1:] 977   } 978   return value, nil 979  } 980   981   982   983   984   985   986   987   988   989   990   991   992   993   994   995   996   997   998   999   1000   1001   1002   1003   1004   1005   1006   1007   1008   1009   1010   1011   1012   1013   1014   1015   1016   1017   1018   1019   1020   1021   1022   1023  func Parse(layout, value string) (Time, error) { 1024   1025   if layout == RFC3339 || layout == RFC3339Nano { 1026   if t, ok := parseRFC3339(value, Local); ok { 1027   return t, nil 1028   } 1029   } 1030   return parse(layout, value, UTC, Local) 1031  } 1032   1033   1034   1035   1036   1037   1038  func ParseInLocation(layout, value string, loc *Location) (Time, error) { 1039   1040   if layout == RFC3339 || layout == RFC3339Nano { 1041   if t, ok := parseRFC3339(value, loc); ok { 1042   return t, nil 1043   } 1044   } 1045   return parse(layout, value, loc, loc) 1046  } 1047   1048  func parse(layout, value string, defaultLocation, local *Location) (Time, error) { 1049   alayout, avalue := layout, value 1050   rangeErrString := "" 1051   amSet := false
1052   pmSet := false
1053   1054   1055   var ( 1056   year int 1057   month int = -1 1058   day int = -1 1059   yday int = -1 1060   hour int 1061   min int 1062   sec int 1063   nsec int 1064   z Location 1065   zoneOffset int = -1 1066   zoneName string 1067   ) 1068   1069   1070   for { 1071   var err error 1072   prefix, std, suffix := nextStdChunk(layout) 1073   stdstr := layout[len(prefix) : len(layout)-len(suffix)] 1074   value, err = skip(value, prefix) 1075   if err != nil { 1076   return Time{}, newParseError(alayout, avalue, prefix, value, "") 1077   } 1078   if std == 0 { 1079   if len(value) != 0 { 1080   return Time{}, newParseError(alayout, avalue, "", value, ": extra text: "+quote(value)) 1081   } 1082   break 1083   } 1084   layout = suffix 1085   var p string 1086   hold := value 1087   switch std & stdMask { 1088   case stdYear: 1089   if len(value) < 2 { 1090   err = errBad 1091   break 1092   } 1093   p, value = value[0:2], value[2:] 1094   year, err = atoi(p) 1095   if err != nil { 1096   break 1097   } 1098   if year >= 69 { 1099   year += 1900 1100   } else { 1101   year += 2000 1102   } 1103   case stdLongYear: 1104   if len(value) < 4 || !isDigit(value, 0) { 1105   err = errBad 1106   break 1107   } 1108   p, value = value[0:4], value[4:] 1109   year, err = atoi(p) 1110   case stdMonth: 1111   month, value, err = lookup(shortMonthNames, value) 1112   month++ 1113   case stdLongMonth: 1114   month, value, err = lookup(longMonthNames, value) 1115   month++ 1116   case stdNumMonth, stdZeroMonth: 1117   month, value, err = getnum(value, std == stdZeroMonth) 1118   if err == nil && (month <= 0 || 12 < month) { 1119   rangeErrString = "month" 1120   } 1121   case stdWeekDay: 1122   1123   _, value, err = lookup(shortDayNames, value) 1124   case stdLongWeekDay: 1125   _, value, err = lookup(longDayNames, value) 1126   case stdDay, stdUnderDay, stdZeroDay: 1127   if std == stdUnderDay && len(value) > 0 && value[0] == ' ' { 1128   value = value[1:] 1129   } 1130   day, value, err = getnum(value, std == stdZeroDay) 1131   1132   1133   case stdUnderYearDay, stdZeroYearDay: 1134   for i := 0; i < 2; i++ { 1135   if std == stdUnderYearDay && len(value) > 0 && value[0] == ' ' { 1136   value = value[1:] 1137   } 1138   } 1139   yday, value, err = getnum3(value, std == stdZeroYearDay) 1140   1141   1142   case stdHour: 1143   hour, value, err = getnum(value, false) 1144   if hour < 0 || 24 <= hour { 1145   rangeErrString = "hour" 1146   } 1147   case stdHour12, stdZeroHour12: 1148   hour, value, err = getnum(value, std == stdZeroHour12) 1149   if hour < 0 || 12 < hour { 1150   rangeErrString = "hour" 1151   } 1152   case stdMinute, stdZeroMinute: 1153   min, value, err = getnum(value, std == stdZeroMinute) 1154   if min < 0 || 60 <= min { 1155   rangeErrString = "minute" 1156   } 1157   case stdSecond, stdZeroSecond: 1158   sec, value, err = getnum(value, std == stdZeroSecond) 1159   if err != nil { 1160   break 1161   } 1162   if sec < 0 || 60 <= sec { 1163   rangeErrString = "second" 1164   break 1165   } 1166   1167   1168   if len(value) >= 2 && commaOrPeriod(value[0]) && isDigit(value, 1) { 1169   _, std, _ = nextStdChunk(layout) 1170   std &= stdMask 1171   if std == stdFracSecond0 || std == stdFracSecond9 { 1172   1173   break 1174   } 1175   1176   n := 2 1177   for ; n < len(value) && isDigit(value, n); n++ { 1178   } 1179   nsec, rangeErrString, err = parseNanoseconds(value, n) 1180   value = value[n:] 1181   } 1182   case stdPM: 1183   if len(value) < 2 { 1184   err = errBad 1185   break 1186   } 1187   p, value = value[0:2], value[2:] 1188   switch p { 1189   case "PM": 1190   pmSet = true 1191   case "AM": 1192   amSet = true 1193   default: 1194   err = errBad 1195   } 1196   case stdpm: 1197   if len(value) < 2 { 1198   err = errBad 1199   break 1200   } 1201   p, value = value[0:2], value[2:] 1202   switch p { 1203   case "pm": 1204   pmSet = true 1205   case "am": 1206   amSet = true 1207   default: 1208   err = errBad 1209   } 1210   case stdISO8601TZ, stdISO8601ShortTZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ: 1211   if len(value) >= 1 && value[0] == 'Z' { 1212   value = value[1:] 1213   z = UTC 1214   break 1215   } 1216   fallthrough 1217   case stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ: 1218   var sign, hour, min, seconds string 1219   if std == stdISO8601ColonTZ || std == stdNumColonTZ { 1220   if len(value) < 6 { 1221   err = errBad 1222   break 1223   } 1224   if value[3] != ':' { 1225   err = errBad 1226   break 1227   } 1228   sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:] 1229   } else if std == stdNumShortTZ || std == stdISO8601ShortTZ { 1230   if len(value) < 3 { 1231   err = errBad 1232   break 1233   } 1234   sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:] 1235   } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ { 1236   if len(value) < 9 { 1237   err = errBad 1238   break 1239   } 1240   if value[3] != ':' || value[6] != ':' { 1241   err = errBad 1242   break 1243   } 1244   sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:] 1245   } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz { 1246   if len(value) < 7 { 1247   err = errBad 1248   break 1249   } 1250   sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:] 1251   } else { 1252   if len(value) < 5 { 1253   err = errBad 1254   break 1255   } 1256   sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:] 1257   } 1258   var hr, mm, ss int 1259   hr, _, err = getnum(hour, true) 1260   if err == nil { 1261   mm, _, err = getnum(min, true) 1262   if err == nil { 1263   ss, _, err = getnum(seconds, true) 1264   } 1265   } 1266   1267   1268   1269   1270   if hr > 24 { 1271   rangeErrString = "time zone offset hour" 1272   } 1273   if mm > 60 { 1274   rangeErrString = "time zone offset minute" 1275   } 1276   if ss > 60 { 1277   rangeErrString = "time zone offset second" 1278   } 1279   1280   zoneOffset = (hr60+mm)*60 + ss 1281   switch sign[0] { 1282   case '+': 1283   case '-': 1284   zoneOffset = -zoneOffset 1285   default: 1286   err = errBad 1287   } 1288   case stdTZ: 1289   1290   if len(value) >= 3 && value[0:3] == "UTC" { 1291   z = UTC 1292   value = value[3:] 1293   break 1294   } 1295   n, ok := parseTimeZone(value) 1296   if !ok { 1297   err = errBad 1298   break 1299   } 1300   zoneName, value = value[:n], value[n:] 1301   1302   case stdFracSecond0: 1303   1304   1305   ndigit := 1 + digitsLen(std) 1306   if len(value) < ndigit { 1307   err = errBad 1308   break 1309   } 1310   nsec, rangeErrString, err = parseNanoseconds(value, ndigit) 1311   value = value[ndigit:] 1312   1313   case stdFracSecond9: 1314   if len(value) < 2 || !commaOrPeriod(value[0]) || value[1] < '0' || '9' < value[1] { 1315   1316   break 1317   } 1318   1319   1320   i := 0 1321   for i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' { 1322   i++ 1323   } 1324   nsec, rangeErrString, err = parseNanoseconds(value, 1+i) 1325   value = value[1+i:] 1326   } 1327   if rangeErrString != "" { 1328   return Time{}, newParseError(alayout, avalue, stdstr, value, ": "+rangeErrString+" out of range") 1329   } 1330   if err != nil { 1331   return Time{}, newParseError(alayout, avalue, stdstr, hold, "") 1332   } 1333   } 1334   if pmSet && hour < 12 { 1335   hour += 12 1336   } else if amSet && hour == 12 { 1337   hour = 0 1338   } 1339   1340   1341   if yday >= 0 { 1342   var d int 1343   var m int 1344   if isLeap(year) { 1345   if yday == 31+29 { 1346   m = int(February) 1347   d = 29 1348   } else if yday > 31+29 { 1349   yday-- 1350   } 1351   } 1352   if yday < 1 || yday > 365 { 1353   return Time{}, newParseError(alayout, avalue, "", value, ": day-of-year out of range") 1354   } 1355   if m == 0 { 1356   m = (yday-1)/31 + 1 1357   if daysBefore(Month(m+1)) < yday { 1358   m++ 1359   } 1360   d = yday - daysBefore(Month(m)) 1361   } 1362   1363   1364   if month >= 0 && month != m { 1365   return Time{}, newParseError(alayout, avalue, "", value, ": day-of-year does not match month") 1366   } 1367   month = m 1368   if day >= 0 && day != d { 1369   return Time{}, newParseError(alayout, avalue, "", value, ": day-of-year does not match day") 1370   } 1371   day = d 1372   } else { 1373   if month < 0 { 1374   month = int(January) 1375   } 1376   if day < 0 { 1377   day = 1 1378   } 1379   } 1380   1381   1382   if day < 1 || day > daysIn(Month(month), year) { 1383   return Time{}, newParseError(alayout, avalue, "", value, ": day out of range") 1384   } 1385   1386   if z != nil { 1387   return Date(year, Month(month), day, hour, min, sec, nsec, z), nil 1388   } 1389   1390   if zoneOffset != -1 { 1391   t := Date(year, Month(month), day, hour, min, sec, nsec, UTC) 1392   t.addSec(-int64(zoneOffset)) 1393   1394   1395   1396   name, offset, _, _, _ := local.lookup(t.unixSec()) 1397   if offset == zoneOffset && (zoneName == "" || name == zoneName) { 1398   t.setLoc(local) 1399   return t, nil 1400   } 1401   1402   1403   zoneNameCopy := stringslite.Clone(zoneName) 1404   t.setLoc(FixedZone(zoneNameCopy, zoneOffset)) 1405   return t, nil 1406   } 1407   1408   if zoneName != "" { 1409   t := Date(year, Month(month), day, hour, min, sec, nsec, UTC) 1410   1411   1412   offset, ok := local.lookupName(zoneName, t.unixSec()) 1413   if ok { 1414   t.addSec(-int64(offset)) 1415   t.setLoc(local) 1416   return t, nil 1417   } 1418   1419   1420   if len(zoneName) > 3 && zoneName[:3] == "GMT" { 1421   offset, _ = atoi(zoneName[3:]) 1422   offset *= 3600 1423   } 1424   zoneNameCopy := stringslite.Clone(zoneName) 1425   t.setLoc(FixedZone(zoneNameCopy, offset)) 1426   return t, nil 1427   } 1428   1429   1430   return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil 1431  } 1432   1433   1434   1435   1436   1437   1438   1439   1440   1441   1442   1443  func parseTimeZone(value string) (length int, ok bool) { 1444   if len(value) < 3 { 1445   return 0, false 1446   } 1447   1448   if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") { 1449   return 4, true 1450   } 1451   1452   if value[:3] == "GMT" { 1453   length = parseGMT(value) 1454   return length, true 1455   } 1456   1457   if value[0] == '+' || value[0] == '-' { 1458   length = parseSignedOffset(value) 1459   ok := length > 0 1460   return length, ok 1461   } 1462   1463   var nUpper int 1464   for nUpper = 0; nUpper < 6; nUpper++ { 1465   if nUpper >= len(value) { 1466   break 1467   } 1468   if c := value[nUpper]; c < 'A' || 'Z' < c { 1469   break 1470   } 1471   } 1472   switch nUpper { 1473   case 0, 1, 2, 6: 1474   return 0, false 1475   case 5: 1476   if value[4] == 'T' { 1477   return 5, true 1478   } 1479   case 4: 1480   1481   if value[3] == 'T' || value[:4] == "WITA" { 1482   return 4, true 1483   } 1484   case 3: 1485   return 3, true 1486   } 1487   return 0, false 1488  } 1489   1490   1491   1492   1493  func parseGMT(value string) int { 1494   value = value[3:] 1495   if len(value) == 0 { 1496   return 3 1497   } 1498   1499   return 3 + parseSignedOffset(value) 1500  } 1501   1502   1503   1504   1505  func parseSignedOffset(value string) int { 1506   sign := value[0] 1507   if sign != '-' && sign != '+' { 1508   return 0 1509   } 1510   x, rem, err := leadingInt(value[1:]) 1511   1512   1513   if err != nil || value[1:] == rem { 1514   return 0 1515   } 1516   if x > 23 { 1517   return 0 1518   } 1519   return len(value) - len(rem) 1520  } 1521   1522  func commaOrPeriod(b byte) bool { 1523   return b == '.' || b == ',' 1524  } 1525   1526  func parseNanoseconds[bytes []byte | string](value bytes, nbytes int) (ns int, rangeErrString string, err error) { 1527   if !commaOrPeriod(value[0]) { 1528   err = errBad 1529   return 1530   } 1531   if nbytes > 10 { 1532   value = value[:10] 1533   nbytes = 10 1534   } 1535   if ns, err = atoi(value[1:nbytes]); err != nil { 1536   return 1537   } 1538   if ns < 0 { 1539   rangeErrString = "fractional second" 1540   return 1541   } 1542   1543   1544   scaleDigits := 10 - nbytes 1545   for i := 0; i < scaleDigits; i++ { 1546   ns *= 10 1547   } 1548   return 1549  } 1550   1551  var errLeadingInt = errors.New("time: bad [0-9]*") 1552   1553   1554  func leadingInt[bytes []byte | string](s bytes) (x uint64, rem bytes, err error) { 1555   i := 0 1556   for ; i < len(s); i++ { 1557   c := s[i] 1558   if c < '0' || c > '9' { 1559   break 1560   } 1561   if x > 1<<63/10 { 1562   1563   return 0, rem, errLeadingInt 1564   } 1565   x = x*10 + uint64(c) - '0' 1566   if x > 1<<63 { 1567   1568   return 0, rem, errLeadingInt 1569   } 1570   } 1571   return x, s[i:], nil 1572  } 1573   1574   1575   1576   1577  func leadingFraction(s string) (x uint64, scale float64, rem string) { 1578   i := 0 1579   scale = 1 1580   overflow := false 1581   for ; i < len(s); i++ { 1582   c := s[i] 1583   if c < '0' || c > '9' { 1584   break 1585   } 1586   if overflow { 1587   continue 1588   } 1589   if x > (1<<63-1)/10 { 1590   1591   overflow = true 1592   continue 1593   } 1594   y := x*10 + uint64(c) - '0' 1595   if y > 1<<63 { 1596   overflow = true 1597   continue 1598   } 1599   x = y 1600   scale *= 10 1601   } 1602   return x, scale, s[i:] 1603  } 1604   1605  var unitMap = map[string]uint64{ 1606   "ns": uint64(Nanosecond), 1607   "us": uint64(Microsecond), 1608   "µs": uint64(Microsecond), 1609   "μs": uint64(Microsecond), 1610   "ms": uint64(Millisecond), 1611   "s": uint64(Second), 1612   "m": uint64(Minute), 1613   "h": uint64(Hour), 1614  } 1615   1616   1617   1618   1619   1620   1621  func ParseDuration(s string) (Duration, error) { 1622   1623   orig := s 1624   var d uint64 1625   neg := false 1626   1627   1628   if s != "" { 1629   c := s[0] 1630   if c == '-' || c == '+' { 1631   neg = c == '-' 1632   s = s[1:] 1633   } 1634   } 1635   1636   if s == "0" { 1637   return 0, nil 1638   } 1639   if s == "" { 1640   return 0, errors.New("time: invalid duration " + quote(orig)) 1641   } 1642   for s != "" { 1643   var ( 1644   v, f uint64
1645   scale float64 = 1 1646   ) 1647   1648   var err error 1649   1650   1651   if !(s[0] == '.' || '0' <= s[0] && s[0] <= '9') { 1652   return 0, errors.New("time: invalid duration " + quote(orig)) 1653   } 1654   1655   pl := len(s) 1656   v, s, err = leadingInt(s) 1657   if err != nil { 1658   return 0, errors.New("time: invalid duration " + quote(orig)) 1659   } 1660   pre := pl != len(s) 1661   1662   1663   post := false 1664   if s != "" && s[0] == '.' { 1665   s = s[1:] 1666   pl := len(s) 1667   f, scale, s = leadingFraction(s) 1668   post = pl != len(s) 1669   } 1670   if !pre && !post { 1671   1672   return 0, errors.New("time: invalid duration " + quote(orig)) 1673   } 1674   1675   1676   i := 0 1677   for ; i < len(s); i++ { 1678   c := s[i] 1679   if c == '.' || '0' <= c && c <= '9' { 1680   break 1681   } 1682   } 1683   if i == 0 { 1684   return 0, errors.New("time: missing unit in duration " + quote(orig)) 1685   } 1686   u := s[:i] 1687   s = s[i:] 1688   unit, ok := unitMap[u] 1689   if !ok { 1690   return 0, errors.New("time: unknown unit " + quote(u) + " in duration " + quote(orig)) 1691   } 1692   if v > 1<<63/unit { 1693   1694   return 0, errors.New("time: invalid duration " + quote(orig)) 1695   } 1696   v *= unit 1697   if f > 0 { 1698   1699   1700   v += uint64(float64(f) * (float64(unit) / scale)) 1701   if v > 1<<63 { 1702   1703   return 0, errors.New("time: invalid duration " + quote(orig)) 1704   } 1705   } 1706   d += v 1707   if d > 1<<63 { 1708   return 0, errors.New("time: invalid duration " + quote(orig)) 1709   } 1710   } 1711   if neg { 1712   return -Duration(d), nil 1713   } 1714   if d > 1<<63-1 { 1715   return 0, errors.New("time: invalid duration " + quote(orig)) 1716   } 1717   return Duration(d), nil 1718  } 1719  

View as plain text