XML中的奇怪日期格式,转换为Ruby DateTime对象

时间:2012-07-02 16:36:19

标签: ruby xml datetime

对谷歌而言,这是一个艰难的过程。我有一个长达一百万行的XML文档,我正在使用Ruby来解析它并删除我不关心的条目。一个我的标准是创建日期。这些XML块中包含有趣的日期

<attribute name="datemodified" type="date">362895460.21263897418975830078</attribute>
<attribute name="datecreated" type="date">356831173.15324598550796508789</attribute>

我从来没有见过完全格式化的日期。它们看起来类似于Time.now.to_f之类的内容。即便如此,我也不知道如何将它们变成Ruby DateTime对象。如果您甚至可以确定如何创建这些时间或它们的含义,那将非常有用。

如果有帮助,这个XML文件最初是由称为“Things”的Mac OS X应用程序创建的。

感谢阅读!

更新:我创建了两个条目并记录了创建它们的时间:

从7月2日至2012年9月57日上午

<attribute name="datemodified" type="date">362941035.01687598228454589844</attribute> 
<attribute name="datecreated" type="date">362940986.89370900392532348633</attribute>

从7月2日至2012年9月5日上午

<attribute name="datemodified" type="date">362941107.69538801908493041992</attribute>
<attribute name="datecreated" type="date">362941080.53793197870254516602</attribute>

我无法达到准确性的第二个,但我确实让它们分开了一分钟......这使得它们看起来实际上是几秒......但是......从一些随机的日期开始。也许开发者的生日:)

做一些快速的数学运算,看起来随机日期是在2000-12-31 16:09:43 -0800左右,或者也许是01/01/01,以便于记忆...而且在几秒钟内即可获得978336000

2 个答案:

答案 0 :(得分:3)

Time.at方法从1970年以来的秒数转换为Time实例:

[1] pry(main)> Time.at 362895460.21263897418975830078
=> 1981-07-02 00:17:40 -0400

如果该日期不正确,但单位为秒,则可以添加常量以获得正确的日期,例如

[2] pry(main)> Time.parse('2001-01-01') - Time.at(0)
=> 978325200.0

答案 1 :(得分:0)

数字在我看来,整数部分是朱利安日期,分数部分是一天的分数。我没有详细调查过。作为参考,Saxon中用于从“Julian instant”转换日期/时间的代码是:

public static DateTimeValue fromJulianInstant(/*@NotNull*/ BigDecimal instant) {
        BigInteger julianSecond = instant.toBigInteger();
        BigDecimal microseconds = instant.subtract(new BigDecimal(julianSecond)).multiply(DecimalValue.BIG_DECIMAL_ONE_MILLION);
        long js = julianSecond.longValue();
        long jd = js / (24L * 60L * 60L);
        DateValue date = DateValue.dateFromJulianDayNumber((int)jd);
        js = js % (24L * 60L * 60L);
        byte hour = (byte)(js / (60L * 60L));
        js = js % (60L * 60L);
        byte minute = (byte)(js / (60L));
        js = js % (60L);
        return new DateTimeValue(date.getYear(), date.getMonth(), date.getDay(),
                hour, minute, (byte)js, microseconds.intValue(),0 , true);
}

public static DateValue dateFromJulianDayNumber(int julianDayNumber) {
        if (julianDayNumber >= 0) {
            int L = julianDayNumber + 68569 + 1;    // +1 adjustment for days starting at noon
            int n = (4 * L) / 146097;
            L = L - (146097 * n + 3) / 4;
            int i = (4000 * (L + 1)) / 1461001;
            L = L - (1461 * i) / 4 + 31;
            int j = (80 * L) / 2447;
            int d = L - (2447 * j) / 80;
            L = j / 11;
            int m = j + 2 - (12 * L);
            int y = 100 * (n - 49) + i + L;
            return new DateValue(y, (byte) m, (byte) d, true);
        } else {
            // add 12000 years and subtract them again...
            DateValue dt = dateFromJulianDayNumber(julianDayNumber +
                    (365 * 12000 + 12000 / 4 - 12000 / 100 + 12000 / 400));
            dt.year -= 12000;
            return dt;
        }
    }