由于1900和1904都早于历元 (即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历),所以需要使用
GregorianCalendar来计算.
其实使用joda计算最方便,但是不能为了这两个计算就引入几百K的jar包.所以自己动手,查了些资料,自己写了出来.
/** * 1900日期系统:电子表格将1900年1月1日保存为序列号2,1900年1月2日保存为序列号3, 1900年1月3日保存为序列号4 …… * 依此类推。<br> * 注意,此计算在秒及其以下单位有误差 * * @param days * @return */ public static Date getDateFrom1900(double days) { GregorianCalendar gc = new GregorianCalendar(1900, 0, 1, 0, 0, 0); int day = (int) days;// 小数点前 gc.add(Calendar.DAY_OF_MONTH, day - 2); double digit = days - day;// 小数点后 if (digit > 0) { int ms = (int) (digit * 24 * 60 * 60 * 1000); gc.add(Calendar.MILLISECOND, ms); } return gc.getTime(); } /** * 1904日期系统:电子表格将1904年1月1日保存为序列号0,将1904年1月2 日保存为序列号1,将 1904年1月3日保存为序列号 2 …… * 依此类推。 * * @param days * @return */ public static Date getDateFrom1904(double days) { GregorianCalendar gc = new GregorianCalendar(1904, 0, 1, 0, 0, 0); int day = (int) days;// 小数点前 gc.add(Calendar.DAY_OF_MONTH, day); double digit = days - day;// 小数点后 if (digit > 0) { int ms = (int) (digit * 24 * 60 * 60 * 1000); gc.add(Calendar.MILLISECOND, ms); } return gc.getTime(); } public static double dateTo1900(Date date) { if (date == null) { throw new NullPointerException(); } GregorianCalendar d1900 = new GregorianCalendar(1900, 0, 1, 0, 0, 0); GregorianCalendar dcurr = new GregorianCalendar(); dcurr.setTime(date); int days = getDaysBetween2Calendar(d1900, dcurr); int hours = dcurr.get(GregorianCalendar.HOUR_OF_DAY); int mins = dcurr.get(GregorianCalendar.MINUTE); int s = dcurr.get(GregorianCalendar.SECOND); int ms = dcurr.get(GregorianCalendar.MILLISECOND); double d = 2 + days + (((hours * 60 + mins) * 60 + s) * 1000 + ms) / (24D * 60 * 60 * 1000) - 1; return d; } public static double dateTo1904(Date date) { if (date == null) { throw new NullPointerException(); } GregorianCalendar d1904 = new GregorianCalendar(1904, 0, 1, 0, 0, 0); GregorianCalendar dcurr = new GregorianCalendar(); dcurr.setTime(date); int days = getDaysBetween2Calendar(d1904, dcurr); int hours = dcurr.get(GregorianCalendar.HOUR_OF_DAY); int mins = dcurr.get(GregorianCalendar.MINUTE); int s = dcurr.get(GregorianCalendar.SECOND); int ms = dcurr.get(GregorianCalendar.MILLISECOND); double d = days + (((hours * 60 + mins) * 60 + s) * 1000 + ms) / (24D * 60 * 60 * 1000) - 1; return d; } private static int getDaysBetween2Calendar(GregorianCalendar gc1, GregorianCalendar gc2) { GregorianCalendar gc1Copy = (GregorianCalendar) gc1.clone(); GregorianCalendar gc2Copy = (GregorianCalendar) gc2.clone(); if (gc1Copy.after(gc2Copy)) { GregorianCalendar temp = gc1Copy; gc1Copy = gc2Copy; gc2Copy = temp; } gc1Copy.clear(GregorianCalendar.MILLISECOND); gc1Copy.clear(GregorianCalendar.SECOND); gc1Copy.clear(GregorianCalendar.MINUTE); gc1Copy.clear(GregorianCalendar.HOUR_OF_DAY); gc2Copy.clear(GregorianCalendar.MILLISECOND); gc2Copy.clear(GregorianCalendar.SECOND); gc2Copy.clear(GregorianCalendar.MINUTE); gc2Copy.clear(GregorianCalendar.HOUR_OF_DAY); int days = 0; while (gc1Copy.before(gc2Copy)) { gc1Copy.add(GregorianCalendar.DAY_OF_MONTH, 1); days++; } return days; }
测试
// 1900 40448.6530580556 2010/9/27 15:40 // 1904 38986.6523888079 2010/9/27 15:39 System.out.println(getDaysBetween2Calendar(new GregorianCalendar(2010, 10, 1), new GregorianCalendar(2010, 10, 2))); System.out.println(getDateFrom1904(38986.6523888079)); System.out.println(getDateFrom1900(40448.6530580556)); System.out.println(dateTo1900(getDateFrom1900(40448.6530580556))); System.out.println(dateTo1904(getDateFrom1904(38986.6523888079)));
结果:
1 Mon Sep 27 15:39:26 GMT 2010 Mon Sep 27 15:40:24 GMT 2010 40448.653058055555 38986.652388807874