代码之家  ›  专栏  ›  技术社区  ›  George

OLIDATE Java实现

  •  3
  • George  · 技术社区  · 14 年前

    我需要一个好的OLIDATE Java实现, this one 似乎不起作用。有没有已知的好的开源实现(比如在apache commons中)?如果没有,我应该在哪里读到它,以便编写自己的实现?

    3 回复  |  直到 9 年前
        1
  •  2
  •   Chris K    14 年前

    这个 Old New Thing blog entry 似乎是一篇关于这个话题的不错的论文:

    ole automation日期格式是一个浮点值,从1899年12月30日午夜算起。小时和分钟表示为小数天。

    如果您可以访问VisualStudio和MFC CaleDeTimeToM源,可以在Java中重新实现它。

        2
  •  3
  •   Koss    11 年前

    请尝试以下代码:

    public static Date getDateFromCOMDate(float comtime) {
        String floatstr = String.valueOf(comtime);
        String [] ss = floatstr.split("\\.");
        long nulltime = -2209183200000L;
        long dayms = 86400000;
        int days = Integer.valueOf(ss[0]);
        float prop = comtime - days;
        long cdayms = Math.round(dayms * prop);
        long time = nulltime + days*dayms + cdayms;
        Date d = new Date(time);
        return d;
    }
    
        3
  •  2
  •   Alexander    9 年前

    以前的实现是错误的,例如1.0和-1.25的日期错误。 以下实现符合MSDN中描述的OLE日期,例如: https://msdn.microsoft.com/en-us/library/system.datetime.tooadate(v=vs.110).aspx

    下面的实现确实符合msdn文档。 它将bigdecimal值转换为joda localdatetime。 bigdecimal比float和double更好,因为它能够保存精确的值。

    class COMDateToRegularDateConverter {
        private static final LocalDateTime ZERO_COM_TIME = new LocalDateTime(1899, 12, 30, 0, 0);
        private static final BigDecimal MILLIS_PER_DAY = new BigDecimal(86400000);
    
        LocalDateTime toLocalDateTime(BigDecimal comTime) {
            BigDecimal daysAfterZero = comTime.setScale(0, RoundingMode.DOWN);
            BigDecimal fraction = comTime.subtract(daysAfterZero).abs(); //fraction always represents the time of that day
            BigDecimal fractionMillisAfterZero = fraction.multiply(MILLIS_PER_DAY).setScale(0, RoundingMode.HALF_DOWN);
    
            return ZERO_COM_TIME.plusDays(daysAfterZero.intValue()).plusMillis(fractionMillisAfterZero.intValue());
        }
    }