Wie konvertiert MS MS Excel Datum von Fließkomma zu Datum Format in Ruby?

8

Versuch, eine XLSX-Datei mit roo gem in einem Ruby-Skript zu analysieren.

In Excel werden Daten als Float oder Integer im Format DDDDD.ttttt gespeichert, gezählt von 1900-01-00 (00 no 01) . Also um ein Datum wie 40396 zu konvertieren - Sie würden 1900-01-00 + 40396 nehmen und Sie sollten 2010-10-15 bekommen, aber ich bekomme 2010-08-08.

Ich verwende active_support / time, um eine Berechnung wie folgt durchzuführen:

%Vor%

Mache ich meine Berechnung falsch oder gibt es einen Fehler bei der aktiven Unterstützung?

Ich habe ruby ​​1.9.3-mri unter Windows 7 + zuletzt active_support gem (3.2.1)

ausgeführt

BEARBEITEN

Ich habe die ältere Datei in Excel mit den falschen Daten angeschaut - mein Skript / meine Konsole hat die richtigen Daten gezogen - daher meine Verwirrung - ich habe alles richtig gemacht, außer die richtige Datei zu benutzen !!!! Verdammt die All-Nighters!

Danke an alle, die antworten. Ich werde die Frage hier für den Fall aufbewahren, dass jemand Informationen darüber benötigt, wie man Daten von Excel mit Ruby konvertiert.

Auch für alle anderen, die in dieses Tabellenkalkulationsprogramm eindringen, wird das Lesen von XLSX-Dateien zu diesem Zeitpunkt (v 0.7.1) NICHT unterstützt. Daher verwende ich roo zum Lesen und axlsx zum Schreiben.

    
konung 11.05.2012, 23:28
quelle

3 Antworten

24

Sie haben einen Tag-für-Schritt-Fehler in Ihrer Tag-Nummerierung - aufgrund eines Fehlers in Lotus 1-2-3, mit dem Excel und andere Tabellenkalkulationsprogramme seit über 30 Jahren sorgfältig kompatibel sind.

Ursprünglich sollte der 1. Tag der 1. Januar 1900 sein (was, wie Sie sagten, Tag 0 gleich dem 31. Dezember 1899 machen würde). Aber Lotus hat 1900 fälschlicherweise für ein Schaltjahr gehalten, daher sind die Tageszahlen für alles vor dem 1. März dieses Jahres zu hoch. Wenn Sie diese Zahlen mit einem Kalender verwenden, der 1900 als gemeinsames Jahr korrekt zählt, wird Tag 1 zum 31. Dezember und Tag 0 wird zurück zum 30. Jahr. So ist die Zeit für die Datumsarithmetik in Lotus-basierten Tabellen der Samstag, der 30. Dezember 1899. (Modernes Excel und einige andere Tabellen erweitern die Kompatibilität mit Lotus-Bugs weit genug, um dieses Datum als "31. Dezember" zu bezeichnen Samstag, aber andere Lotus-basierte Tabellen nicht, und Ruby sicherlich auch nicht.)

Selbst wenn Sie diesen Fehler berücksichtigen, ist Ihr angegebenes Beispiel jedoch falsch: Lotus-Tag-Nummer 40.396 ist der 6. August 2010 und nicht der 15. Oktober. Ich habe diese Übereinstimmung in Excel-, LibreOffice- und Google-Tabellen bestätigt, die alle übereinstimmen. Sie müssen irgendwo Beispiele durchquert haben.

Hier ist eine Möglichkeit, die Konvertierung durchzuführen:

%Vor%

Alternativ können Sie eine andere bekannte Korrespondenz nutzen. Zeit Null für Ruby (und POSIX-Systeme im Allgemeinen) ist der 1. Januar 1970 um Mitternacht GMT. 1. Januar 1970 ist Lotus Tag 25.569. Solange Sie sich daran erinnern, Ihre Berechnungen in UTC durchzuführen, können Sie dies auch tun:

%Vor%

In beiden Fällen möchten Sie wahrscheinlich eine symbolische Konstante für das Epochendatum deklarieren (entweder das Time -Objekt, das 1899-12-30 repräsentiert, oder den POSIX "Tag 0" -Wert 25,569).

Sie können diese Aufrufe in .days durch Multiplikation mit 86.400 ersetzen, wenn Sie active_support/core_ext/integer/time für nichts anderes benötigen und sie nicht nur dafür laden möchten.

    
Mark Reed 12.05.2012, 01:12
quelle
3

Sie tun Ihre Berechnung falsch. Wie kommen Sie zum erwarteten Ergebnis vom 2010-10-15?

In Excel ist 40396 2010-08-06 (natürlich nicht mit dem Kalender 1904). Um das zu demonstrieren, geben Sie 40396 in eine Excel-Zelle ein und setzen Sie das Format auf yyyy-mm-dd .

Alternativ:

%Vor%

Der Kalender von Excel enthält fälschlicherweise 1900-02-29; das ist für einen Tag Unterschied zwischen Ihrem 2010-08-08 Ergebnis; Ich bin mir nicht sicher über den Grund für den zweiten Tag der Differenz.

    
phoog 12.05.2012 01:12
quelle
3

"Excel speichert Datum und Uhrzeit als eine Zahl, die die Anzahl der Tage seit 1900-Jan-0 plus einen Bruchteil eines 24-Stunden-Tages darstellt: ddddd.tttttt. Dies wird als serielles Datum oder serielles Datum / Uhrzeit bezeichnet . " ( Ссылка )

Wenn Ihre Spalte eine Datumszeit und nicht nur ein Datum enthält, ist der folgende Code nützlich:

%Vor%

Beachten Sie auch, dass es in einem Excel-Arbeitsblatt zwei Datumsmodi gibt, 1900-basiert und 1904-basiert, die standardmäßig für auf dem Mac erstellte Tabellen aktiviert sind. Wenn Sie Ihre Daten regelmäßig nach 4 Jahren finden, sollten Sie ein anderes Basisdatum verwenden:

%Vor%

Sie können den 1904-Datumsmodus für jede Tabellenkalkulation aktivieren / deaktivieren. Die Daten erscheinen dann jedoch vier Jahre später in der Tabelle, wenn Sie die Einstellung nach dem Hinzufügen von Daten ändern. Im Allgemeinen sollten Sie immer 1900 Datumsmodus verwenden, da die meisten Excel-Benutzer in der Wildnis Windows-basiert sind.

Hinweis: Ein Fehler bei dieser Methode besteht darin, dass die Rundung +/- 1 Sekunde dauern kann. Für mich sind die Daten, die ich importiere, "nah genug", aber nur etwas, das man im Kopf behalten sollte. Eine bessere Lösung verwendet möglicherweise eine Rundung in Sekundenbruchteilen, um dieses Problem zu beheben.

    
kgx 06.03.2013 16:18
quelle