You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.4KB

  1. var MAX_DATE = 2958465 // about year 9999
  2. var MAX_DATE_1904 = 2957003
  3. // Half a second, expressed in days
  4. var HALF_SECOND = (1.0 / 172800.0)
  5. // Half a millisecond
  6. var HALF_MILLISECOND = (1.0 / 2000.0)
  7. // 从 0000/1/1 到 1900/1/1 的时间序数值
  8. var SERIAL_BASE_NUM = 693959
  9. // 从 0000/1/1 到 1904/1/1 的时间序数值
  10. var SERIAL_BASE_NUM_1904 = 695421
  11. // 指示是否假定 1900 年为润年(兼容 Excel)
  12. var YEAR1900_ISLEAP = 0
  13. // One-based array of days in year at month start
  14. var _afxMonthDays =
  15. [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
  16. var b1904 = false;
  17. var bDisable1900Year = false;
  18. function toTime(dtSrc, b1904) {
  19. var tmDest = {};
  20. var nDays = 0; // Number of days since Dec. 30, 1899
  21. var nDaysAbsolute = 0; // Number of days since 1/1/0
  22. var nSecsInDay = 0; // Time in seconds since midnight
  23. var nMinutesInDay = 0; // Minutes in day
  24. var n400Years = 0; // Number of 400 year increments since 1/1/0
  25. var n400Century = 0; // Century within 400 year block (0,1,2 or 3)
  26. var n4Years = 0; // Number of 4 year increments since 1/1/0
  27. var n4Day = 0; // Day within 4 year block
  28. // (0 is 1/1/yr1, 1460 is 12/31/yr4)
  29. var n4Yr = 0; // Year within 4 year block (0,1,2 or 3)
  30. var bLeap4 = true; // true if 4 year block includes leap year
  31. var bIs1900Year = false; // true if this year is 1900
  32. var dblDate = dtSrc; // tempory serial date
  33. // Round to the second
  34. if (0 == 0)
  35. dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
  36. // If a valid date, then this conversion should not overflow
  37. nDays = Math.floor(dblDate);
  38. nDaysAbsolute = Math.floor(dblDate) + (b1904 ? SERIAL_BASE_NUM_1904 : SERIAL_BASE_NUM); // Add days from 1/1/0 to 12/30/1899
  39. dblDate = Math.abs(dblDate);
  40. var dblSecsInDay = (dblDate - Math.floor(dblDate)) * 86400.0;
  41. nSecsInDay = Math.floor(dblSecsInDay);
  42. // modified by tsingbo:
  43. // Calculate the day of week (sun=0, mon=1...)
  44. // -1 because 1/1/0 is Sat.
  45. tmDest.tm_wday = Math.floor((nDaysAbsolute - 1) % 7);
  46. if (!bDisable1900Year && !b1904 &&
  47. nDaysAbsolute >= SERIAL_BASE_NUM &&
  48. nDaysAbsolute < SERIAL_BASE_NUM + 367) {
  49. bIs1900Year = true;
  50. n4Day = nDaysAbsolute - SERIAL_BASE_NUM;
  51. bLeap4 = true;
  52. n400Years = 4;
  53. n400Century = 3;
  54. n4Yr = 0;
  55. }
  56. else {
  57. // Leap years every 4 yrs except centuries not multiples of 400.
  58. n400Years = Math.floor(nDaysAbsolute / 146097);
  59. // Set nDaysAbsolute to day within 400-year block
  60. nDaysAbsolute %= 146097;
  61. // -1 because first century has extra day
  62. n400Century = Math.floor((nDaysAbsolute - 1) / 36524);
  63. // Non-leap century
  64. if (n400Century != 0) {
  65. // Set nDaysAbsolute to day within century
  66. nDaysAbsolute = (nDaysAbsolute - 1) % 36524;
  67. // +1 because 1st 4 year increment has 1460 days
  68. n4Years = Math.floor((nDaysAbsolute + 1) / 1461);
  69. if (n4Years != 0)
  70. n4Day = Math.floor((nDaysAbsolute + 1) % 1461);
  71. else {
  72. bLeap4 = false;
  73. n4Day = Math.floornDaysAbsolute;
  74. }
  75. }
  76. else {
  77. // Leap century - not special case!
  78. n4Years = Math.floor(nDaysAbsolute / 1461);
  79. n4Day = Math.floor(nDaysAbsolute % 1461);
  80. }
  81. if (bLeap4) {
  82. // -1 because first year has 366 days
  83. n4Yr = (n4Day - 1) / 365;
  84. if (n4Yr != 0)
  85. n4Day = (n4Day - 1) % 365;
  86. }
  87. else {
  88. n4Yr = n4Day / 365;
  89. n4Day %= 365;
  90. }
  91. }
  92. // n4Day is now 0-based day of year. Save 1-based day of year, year number
  93. tmDest.tm_yday = Math.floor(n4Day) + 1;
  94. tmDest.tm_year = Math.floor(n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr);
  95. // Handle leap year: before, on, and after Feb. 29.
  96. if (n4Yr == 0 && bLeap4) {
  97. // Leap Year
  98. if ((!bIs1900Year && n4Day == 59) ||
  99. (bIs1900Year && n4Day == 60)) {
  100. /* Feb. 29 */
  101. tmDest.tm_mon = 2;
  102. tmDest.tm_mday = 29;
  103. }
  104. else {
  105. // Pretend it's not a leap year for month/day comp.
  106. if (n4Day >= 60)
  107. --n4Day;
  108. }
  109. } else {
  110. // Make n4DaY a 1-based day of non-leap year and compute
  111. // month/day for everything but Feb. 29.
  112. if (!bIs1900Year)
  113. ++n4Day;
  114. // Month number always >= n/32, so save some loop time */
  115. for (tmDest.tm_mon = (n4Day >> 5) + 1;
  116. n4Day > _afxMonthDays[tmDest.tm_mon]; tmDest.tm_mon++);
  117. tmDest.tm_mday = Math.floor(n4Day - _afxMonthDays[tmDest.tm_mon - 1]);
  118. }
  119. if (nSecsInDay == 0)
  120. tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
  121. else {
  122. tmDest.tm_sec = Math.floor(nSecsInDay % 60);
  123. nMinutesInDay = nSecsInDay / 60;
  124. tmDest.tm_min = Math.floor(nMinutesInDay % 60);
  125. tmDest.tm_hour = Math.floor(nMinutesInDay / 60);
  126. }
  127. return new Date(tmDest.tm_year, tmDest.tm_mon + 1, tmDest.tm_mday, tmDest.tm_mday, tmDest.tm_min, tmDest.tm_sec);
  128. }