var MAX_DATE = 2958465 // about year 9999 var MAX_DATE_1904 = 2957003 // Half a second, expressed in days var HALF_SECOND = (1.0 / 172800.0) // Half a millisecond var HALF_MILLISECOND = (1.0 / 2000.0) // 从 0000/1/1 到 1900/1/1 的时间序数值 var SERIAL_BASE_NUM = 693959 // 从 0000/1/1 到 1904/1/1 的时间序数值 var SERIAL_BASE_NUM_1904 = 695421 // 指示是否假定 1900 年为润年(兼容 Excel) var YEAR1900_ISLEAP = 0 // One-based array of days in year at month start var _afxMonthDays = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]; var b1904 = false; var bDisable1900Year = false; function toTime(dtSrc, b1904) { var tmDest = {}; var nDays = 0; // Number of days since Dec. 30, 1899 var nDaysAbsolute = 0; // Number of days since 1/1/0 var nSecsInDay = 0; // Time in seconds since midnight var nMinutesInDay = 0; // Minutes in day var n400Years = 0; // Number of 400 year increments since 1/1/0 var n400Century = 0; // Century within 400 year block (0,1,2 or 3) var n4Years = 0; // Number of 4 year increments since 1/1/0 var n4Day = 0; // Day within 4 year block // (0 is 1/1/yr1, 1460 is 12/31/yr4) var n4Yr = 0; // Year within 4 year block (0,1,2 or 3) var bLeap4 = true; // true if 4 year block includes leap year var bIs1900Year = false; // true if this year is 1900 var dblDate = dtSrc; // tempory serial date // Round to the second if (0 == 0) dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND); // If a valid date, then this conversion should not overflow nDays = Math.floor(dblDate); nDaysAbsolute = Math.floor(dblDate) + (b1904 ? SERIAL_BASE_NUM_1904 : SERIAL_BASE_NUM); // Add days from 1/1/0 to 12/30/1899 dblDate = Math.abs(dblDate); var dblSecsInDay = (dblDate - Math.floor(dblDate)) * 86400.0; nSecsInDay = Math.floor(dblSecsInDay); // modified by tsingbo: // Calculate the day of week (sun=0, mon=1...) // -1 because 1/1/0 is Sat. tmDest.tm_wday = Math.floor((nDaysAbsolute - 1) % 7); if (!bDisable1900Year && !b1904 && nDaysAbsolute >= SERIAL_BASE_NUM && nDaysAbsolute < SERIAL_BASE_NUM + 367) { bIs1900Year = true; n4Day = nDaysAbsolute - SERIAL_BASE_NUM; bLeap4 = true; n400Years = 4; n400Century = 3; n4Yr = 0; } else { // Leap years every 4 yrs except centuries not multiples of 400. n400Years = Math.floor(nDaysAbsolute / 146097); // Set nDaysAbsolute to day within 400-year block nDaysAbsolute %= 146097; // -1 because first century has extra day n400Century = Math.floor((nDaysAbsolute - 1) / 36524); // Non-leap century if (n400Century != 0) { // Set nDaysAbsolute to day within century nDaysAbsolute = (nDaysAbsolute - 1) % 36524; // +1 because 1st 4 year increment has 1460 days n4Years = Math.floor((nDaysAbsolute + 1) / 1461); if (n4Years != 0) n4Day = Math.floor((nDaysAbsolute + 1) % 1461); else { bLeap4 = false; n4Day = Math.floornDaysAbsolute; } } else { // Leap century - not special case! n4Years = Math.floor(nDaysAbsolute / 1461); n4Day = Math.floor(nDaysAbsolute % 1461); } if (bLeap4) { // -1 because first year has 366 days n4Yr = (n4Day - 1) / 365; if (n4Yr != 0) n4Day = (n4Day - 1) % 365; } else { n4Yr = n4Day / 365; n4Day %= 365; } } // n4Day is now 0-based day of year. Save 1-based day of year, year number tmDest.tm_yday = Math.floor(n4Day) + 1; tmDest.tm_year = Math.floor(n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr); // Handle leap year: before, on, and after Feb. 29. if (n4Yr == 0 && bLeap4) { // Leap Year if ((!bIs1900Year && n4Day == 59) || (bIs1900Year && n4Day == 60)) { /* Feb. 29 */ tmDest.tm_mon = 2; tmDest.tm_mday = 29; } else { // Pretend it's not a leap year for month/day comp. if (n4Day >= 60) --n4Day; } } else { // Make n4DaY a 1-based day of non-leap year and compute // month/day for everything but Feb. 29. if (!bIs1900Year) ++n4Day; // Month number always >= n/32, so save some loop time */ for (tmDest.tm_mon = (n4Day >> 5) + 1; n4Day > _afxMonthDays[tmDest.tm_mon]; tmDest.tm_mon++); tmDest.tm_mday = Math.floor(n4Day - _afxMonthDays[tmDest.tm_mon - 1]); } if (nSecsInDay == 0) tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0; else { tmDest.tm_sec = Math.floor(nSecsInDay % 60); nMinutesInDay = nSecsInDay / 60; tmDest.tm_min = Math.floor(nMinutesInDay % 60); tmDest.tm_hour = Math.floor(nMinutesInDay / 60); } return new Date(tmDest.tm_year, tmDest.tm_mon + 1, tmDest.tm_mday, tmDest.tm_mday, tmDest.tm_min, tmDest.tm_sec); }