由于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