date.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package xlsx
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. )
  7. //# Pre-calculate the datetime epochs for efficiency.
  8. var (
  9. _JDN_delta = []int{2415080 - 61, 2416482 - 1}
  10. //epoch_1904 = time.Date(1904, 1, 1, 0, 0, 0, 0, time.Local)
  11. //epoch_1900 = time.Date(1899, 12, 31, 0, 0, 0, 0, time.Local)
  12. //epoch_1900_minus_1 = time.Date(1899, 12, 30, 0, 0, 0, 0, time.Local)
  13. _XLDAYS_TOO_LARGE = []int{2958466, 2958466 - 1462} //# This is equivalent to 10000-01-01
  14. )
  15. var (
  16. //ErrXLDateBadTuple = errors.New("XLDate is bad tuple")
  17. //ErrXLDateError = errors.New("XLDateError")
  18. )
  19. func XLDateTooLarge(d float64) error {
  20. return fmt.Errorf("XLDate %v is too large", d)
  21. }
  22. func XLDateAmbiguous(d float64) error {
  23. return fmt.Errorf("XLDate %v is ambiguous", d)
  24. }
  25. func XLDateNegative(d float64) error {
  26. return fmt.Errorf("XLDate %v is Negative", d)
  27. }
  28. func XLDateBadDatemode(datemode int) error {
  29. return fmt.Errorf("XLDate is bad datemode %d", datemode)
  30. }
  31. func divmod(a, b int) (int, int) {
  32. c := a % b
  33. return (a - c) / b, c
  34. }
  35. func div(a, b int) int {
  36. return (a - a%b) / b
  37. }
  38. func max(a, b int) int {
  39. if a > b {
  40. return a
  41. }
  42. return b
  43. }
  44. // this func provide a method to convert date cell string to
  45. // a slice []int. the []int means []int{year, month, day, hour, minute, second}
  46. func StrToDate(data string, datemode int) ([]int, error) {
  47. xldate, err := strconv.ParseFloat(data, 64)
  48. if err != nil {
  49. return nil, err
  50. }
  51. if datemode != 0 && datemode != 1 {
  52. return nil, XLDateBadDatemode(datemode)
  53. }
  54. if xldate == 0.00 {
  55. return []int{0, 0, 0, 0, 0, 0}, nil
  56. }
  57. if xldate < 0.00 {
  58. return nil, XLDateNegative(xldate)
  59. }
  60. xldays := int(xldate)
  61. frac := xldate - float64(xldays)
  62. seconds := int(math.Floor(frac * 86400.0))
  63. hour, minute, second := 0, 0, 0
  64. //assert 0 <= seconds <= 86400
  65. if seconds == 86400 {
  66. xldays += 1
  67. } else {
  68. //# second = seconds % 60; minutes = seconds // 60
  69. var minutes int
  70. minutes, second = divmod(seconds, 60)
  71. //# minute = minutes % 60; hour = minutes // 60
  72. hour, minute = divmod(minutes, 60)
  73. }
  74. if xldays >= _XLDAYS_TOO_LARGE[datemode] {
  75. return nil, XLDateTooLarge(xldate)
  76. }
  77. if xldays == 0 {
  78. return []int{0, 0, 0, hour, minute, second}, nil
  79. }
  80. if xldays < 61 && datemode == 0 {
  81. return nil, XLDateAmbiguous(xldate)
  82. }
  83. jdn := xldays + _JDN_delta[datemode]
  84. yreg := ((((jdn*4+274277)/146097)*3/4)+jdn+1363)*4 + 3
  85. mp := ((yreg%1461)/4)*535 + 333
  86. d := ((mp % 16384) / 535) + 1
  87. //# mp /= 16384
  88. mp >>= 14
  89. if mp >= 10 {
  90. return []int{(yreg / 1461) - 4715, mp - 9, d, hour, minute, second}, nil
  91. }
  92. return []int{(yreg / 1461) - 4716, mp + 3, d, hour, minute, second}, nil
  93. }