Data Excela do znacznika czasu Unix

85

Czy ktoś wie, jak przekonwertować datę Excela na poprawny znacznik czasu Unix?

Hagbard
źródło
Co masz na myśli przez „datę Excela”? Czy masz na myśli tekst sformatowany jako czytelny dla człowieka ciąg daty i godziny "11/09/2009 3:23:24 PM"?
Matt Ball
4
Nie zapominaj, że 19 stycznia 2038 uniksowy znacznik czasu przestanie działać z powodu przepełnienia 32-bitowego. Do tego momentu miliony aplikacji będą musiały albo przyjąć nową konwencję dla znaczników czasu, albo zostaną przeniesione do systemów 64-bitowych, co da znacznikowi czasu „nieco” więcej czasu.
13
bardziej jak 32 bity więcej czasu.
user606723

Odpowiedzi:

107

Żadne z nich nie zadziałało ... kiedy przekonwertowałem znacznik czasu z powrotem, minęły 4 lata.

To działało idealnie: =(A2-DATE(1970,1,1))*86400

Podziękowania dla: Filip Czaja http://fczaja.blogspot.ca

Oryginalny post: http://fczaja.blogspot.ca/2011/06/convert-excel-date-into-timestamp.html

Cybercampbell
źródło
6
Nie zapomnij swojej strefy czasowej (chyba że jesteś w UTC i nie obserwujesz czasu letniego). Epoka UNIX jest niezależna od strefy czasowej, podczas gdy arkusze kalkulacyjne nie. Oto przewodnik z przykładami.
Adam Katz
GMT + 8:=((A1+28800)/86400)+25569
Ivan Chau
aktualny czas dla CDT (środkowy czas letni):=(NOW()-DATE(1970,1,1))*86400 + 5*3600
hBrent
Nowoczesne wersje programu Excel będą narzekać na powyższą formułę, chyba że (1970;1;1)
Jose Luis Blanco
1
@tonygil Będzie działać, jeśli komórki, na które celujesz, są w rzeczywistości datami w programie Excel. Jeśli jest to tekst, który ma reprezentować datę, wszystkie zakłady są wyłączone.
Casey
75

Windows i Mac Excel (2011):

Unix Timestamp = (Excel Timestamp - 25569) * 86400
Excel Timestamp =  (Unix Timestamp / 86400) + 25569

MAC OS X (2007):

Unix Timestamp = (Excel Timestamp - 24107) * 86400
Excel Timestamp =  (Unix Timestamp / 86400) + 24107

Na przykład:

86400 = Seconds in a day
25569 = Days between 1970/01/01 and 1900/01/01 (min date in Windows Excel)
24107 = Days between 1970/01/01 and 1904/01/02 (min date in Mac Excel 2007)
Jeff Wu
źródło
3
Wydaje się, że pakiet Office 2011 na komputerze Mac działa dobrze z wersją tych formuł dla systemu Windows. Wersje „Mac” są na nim daleko.
radicand
1
Myślę, że odwróciłeś znaczniki czasu programu Excel i unix w tych formułach. Uniksowy znacznik czasu to liczba sekund, a więc musi być podzielony przez 86400, a nie przez znacznik czasu programu Excel, jak mówią formuły. Zobacz odpowiedź @ radicand.
Mike Houston
Dzięki za komentarze, przetestowałem to na Mac Excel 2011 i wygląda na to, że są takie same jak wersja dla Windows.
Jeff Wu,
Czy istnieje sposób na przekształcenie uniksowego znacznika czasu w milisekundach na datę i godzinę, zachowując milisekundy?
Lorenzo Belli
mówi człowiek na przepełnieniu stosu. tak, a co z sekundami przestępnymi, profesorze.
katamfetamina,
11

Jeśli założymy, że data w Excelu jest w komórce A1 sformatowanej jako Data, a znacznik czasu Unix powinien znajdować się w komórce A2 sformatowanej jako liczba, formuła w A2 powinna wyglądać:

= (A1 * 86400) - 2209075200

gdzie:

86400 to liczba sekund w ciągu dnia 2209075200 to liczba sekund między 1900-01-01 a 1970-01-01, które są podstawowymi datami dla znaczników czasu w programach Excel i Unix.

Powyższe dotyczy systemu Windows. Na komputerze Mac podstawową datą w programie Excel jest 1904-01-01, a liczbę sekund należy poprawić na: 2082844800

Grendler
źródło
Przynajmniej nie działa dokładnie na oknach. Wyłącza się o 19 godzin.
LLBBL
4
Powinno więc wyglądać tak: = (A1 * 86400) - 2209143600
LLBBL,
2
Domyślną podstawą daty Mac Excel jest 1904, podczas gdy w Windows Excel jest to 1900, ale możesz zmienić podstawę daty w Mac Excel, odznaczając opcję „użyj systemu daty 1904” w preferencjach / obliczeniach, wtedy działa jak Windows Excel.
Cloudranger
6

Oto mapowanie w celach informacyjnych, zakładając UTC dla systemów arkuszy kalkulacyjnych, takich jak Microsoft Excel:

                         Unix  Excel Mac    Excel    Human Date  Human Time
Excel Epoch       -2209075200      -1462        0    1900/01/00* 00:00:00 (local)
Excel ≤ 2011 Mac† -2082758400          0     1462    1904/12/31  00:00:00 (local)
Unix Epoch                  0      24107    25569    1970/01/01  00:00:00 UTC
Example Below      1234567890      38395.6  39857.6  2009/02/13  23:31:30 UTC
Signed Int Max     2147483648      51886    50424    2038/01/19  03:14:08 UTC

One Second                  1       0.0000115740…             —  00:00:01
One Hour                 3600       0.0416666666…             ―  01:00:00
One Day                 86400          1        1             ―  24:00:00

*   „Jan Zero, 1900” to 1899/12/31; zobacz sekcję Błędy poniżej. Excel 2011 dla komputerów Mac (i starsze) używają systemu daty 1904 .

 

Jak często korzystają awkz procesem CSV i zawartości przestrzeni oddzielonych, opracowałem sposób przekonwertować UNIX epoka do stref czasowych / DST -appropriate datę Excel format:

echo 1234567890 |awk '{ 
  # tries GNU date, tries BSD date on failure
  cmd = sprintf("date -d@%d +%%z 2>/dev/null || date -jf %%s %d +%%z", $1, $1)
  cmd |getline tz                                # read in time-specific offset
  hours = substr(tz, 2, 2) + substr(tz, 4) / 60  # hours + minutes (hi, India)
  if (tz ~ /^-/) hours *= -1                     # offset direction (east/west)
  excel = $1/86400 + hours/24 + 25569            # as days, plus offset
  printf "%.9f\n", excel
}'

Użyłem echow tym przykładzie, ale możesz potokować plik, w którym pierwsza kolumna (dla pierwszej komórki w formacie .csv, nazwij ją jako awk -F,) jest epoką UNIX. Zmień, $1aby przedstawić żądany numer kolumny / komórki lub zamiast tego użyj zmiennej.

Powoduje to wywołanie systemowe date. Jeśli niezawodnie będziesz mieć wersję GNU, możesz usunąć 2>/dev/null || date … +%%zi drugą wersję , $1. Biorąc pod uwagę, jak powszechne jest GNU, nie polecałbym zakładać wersji BSD.

getlineCzyta przesunięcia strefy czasowej wyprowadzony przez date +%zsię tz, który jest następnie przetłumaczone na hours. Format będzie podobny do -0700( PDT ) lub +0530( IST ), więc pierwszy wyodrębniony podciąg to 07lub 05, drugi to 00lub 30(następnie podzielony przez 60 w celu wyrażenia w godzinach), a trzecie użycie tzsprawdza, czy nasze przesunięcie jest ujemne i zmienia hoursJeśli potrzebne.

Formuła podana we wszystkich innych odpowiedziach na tej stronie służy do ustawiania excel, z dodatkiem dostosowania strefy czasowej uwzględniającej czas letni jako hours/24.

Jeśli korzystasz ze starszej wersji programu Excel dla komputerów Mac, musisz użyć 24107zamiast 25569(zobacz mapowanie powyżej).

Aby przekonwertować dowolny czas nieokresowy na czas zgodny z Excelem z datą GNU:

echo "last thursday" |awk '{ 
  cmd = sprintf("date -d \"%s\" +\"%%s %%z\"", $0)
  cmd |getline
  hours = substr($2, 2, 2) + substr($2, 4) / 60
  if ($2 ~ /^-/) hours *= -1
  excel = $1/86400 + hours/24 + 25569
  printf "%.9f\n", excel
}'

Jest to w zasadzie ten sam kod, ale date -dnie ma już @symbolu reprezentującego epokę uniksową (biorąc pod uwagę, jak zdolny jest parser ciągów, jestem właściwie zaskoczony, że @jest obowiązkowy; jaki inny format daty ma 9-10 cyfr?) I teraz jest pytany dla dwóch wyjść: epoki i przesunięcia strefy czasowej. Możesz więc użyć np. @1234567890Jako wejścia.

Pluskwa

Lotus 1-2-3 (oryginalne oprogramowanie do obsługi arkuszy kalkulacyjnych) celowo potraktował rok 1900 jako rok przestępny, mimo że tak nie było (zmniejszyło to bazę kodów w momencie, gdy liczył się każdy bajt). Microsoft Excel zachował ten błąd ze względu na kompatybilność, pomijając dzień 60 (fikcyjny 1900/02/29), zachowując mapowanie dnia 59 Lotus 1-2-3 do 1900/02/28. LibreOffice zamiast tego przypisał dzień 60 do 1900/02/28 i cofnął wszystkie poprzednie dni o jeden.

Dowolna data przed 1900/03/01 może oznaczać nawet dzień wolny:

Day        Excel   LibreOffice
-1            -1    1899/12/29
 0    1900/01/00*   1899/12/30
 1    1900/01/01    1899/12/31
 2    1900/01/02    1900/01/0159    1900/02/28    1900/02/27
60    1900/02/29(!) 1900/02/28
61    1900/03/01    1900/03/01

Excel nie uznaje dat ujemnych i ma specjalną definicję Zeroth stycznia (1899/12/31) dla dnia zerowego. Wewnętrznie program Excel rzeczywiście obsługuje daty ujemne (w końcu są to tylko liczby), ale wyświetla je jako liczby, ponieważ nie wie, jak wyświetlić je jako daty (ani nie może konwertować starszych dat na liczby ujemne). 29 lutego 1900 roku, dzień, który nigdy się nie wydarzył, jest rozpoznawany przez Excel, ale nie przez LibreOffice.

Adam Katz
źródło
3

Ponieważ moje zmiany w powyższym zostały odrzucone (czy ktoś z was faktycznie próbował?), Oto, czego naprawdę potrzebujesz, aby to zadziałało:

Windows (i Mac Office 2011+):

  • Unix Timestamp = (Excel Timestamp - 25569) * 86400
  • Znacznik czasu programu Excel = (Unix Timestamp / 86400) + 25569

MAC OS X (przed Office 2011):

  • Unix Timestamp = (Excel Timestamp - 24107) * 86400
  • Znacznik czasu programu Excel = (Unix Timestamp / 86400) + 24107
radicand
źródło
2

Najwyraźniej tracisz jeden dzień, dokładnie 86400 sekund. Użyj numeru 2209161600, a nie numeru 2209075200. Jeśli wygooglujesz dwa numery, znajdziesz wsparcie dla powyższych. Wypróbowałem twoją formułę, ale zawsze zbliżał się 1 dzień inny niż mój serwer. Nie jest to oczywiste ze znacznika czasu unixowego, chyba że myślisz w systemie UNIX zamiast w czasie ludzkim ;-), ale jeśli dwukrotnie sprawdzisz, zobaczysz, że może to być poprawne.

znak
źródło
To prawda, ponieważ program Excel oblicza pierwszy rok jako rok przestępny, mimo że tak nie jest.
ANisus
Mogę potwierdzić, że magiczna liczba to rzeczywiście 2209161600, czyli 1970-01-01 - 1900-01-01 + 1 dzień * 86400. Jeśli wpiszesz 1900-01-01 w programie Excel i zapiszesz jako format sylk i przejrzysz plik w edytor tekstu, który zobaczysz, zapisuje tę datę jako 1 zamiast zera tak, jak powinien, dlatego musisz dodać 1 dzień
Cloudranger
1

Miałem starą bazę danych Excela z datami „czytelnymi dla człowieka”, np. 2010.03.28 20:12:30 Te daty były w UTC + 1 (CET) i musiałem je przekonwertować na czas epoki.

I używana = (A4 DATA (1970; 1: 1)) * 86400-3600 wzór konwersji daty do czasu, epoka z kolumny A do wartości w kolumnie B. Sprawdź przesunięcie strefy czasowej i zrób z nim matematykę. 1 godzina to 3600 sekund.

Jedyną rzeczą, dla której piszę tutaj odpowiedź, widać, że ten temat ma ponad 5 lat, to to, że używam nowych wersji Excela, a także czerwonych postów w tym temacie, ale są one niepoprawne. DATA (1970; 1; 1). Tutaj lata 1970 i styczeń trzeba oddzielić; a nie z,

Jeśli również napotykasz ten problem, miej nadzieję, że to pomoże. Miłego dnia :)

Sorbán Béla
źródło
0

Żadna z obecnych odpowiedzi nie działała dla mnie, ponieważ moje dane były w tym formacie od strony uniksowej:

2016-02-02 19:21:42 UTC

Musiałem przekonwertować to na Epochę, aby umożliwić odwoływanie się do innych danych, które miały znaczniki czasu epoki.

  1. Utwórz nową kolumnę dla części daty i przeanalizuj tę formułę

    =DATEVALUE(MID(A2,6,2) & "/" & MID(A2,9,2) & "/" & MID(A2,1,4)) 
    
  2. Jak już powiedział inny Grendler, utwórz kolejną kolumnę

    =(B2-DATE(1970,1,1))*86400 
    
  3. Utwórz kolejną kolumnę z sumowanym czasem, aby uzyskać całkowitą liczbę sekund:

    =(VALUE(MID(A2,12,2))*60*60+VALUE(MID(A2,15,2))*60+VALUE(MID(A2,18,2)))
    
  4. Utwórz ostatnią kolumnę, która po prostu dodaje do siebie dwie ostatnie kolumny:

    =C2+D2
    
Dranyar
źródło
0

Oto moja ostateczna odpowiedź na to pytanie.

Najwyraźniej również new Date(year, month, day)konstruktor javascript nie uwzględnia sekund przestępnych.

// Parses an Excel Date ("serial") into a
// corresponding javascript Date in UTC+0 timezone.
//
// Doesn't account for leap seconds.
// Therefore is not 100% correct.
// But will do, I guess, since we're
// not doing rocket science here.
//
// https://www.pcworld.com/article/3063622/software/mastering-excel-date-time-serial-numbers-networkdays-datevalue-and-more.html
// "If you need to calculate dates in your spreadsheets,
//  Excel uses its own unique system, which it calls Serial Numbers".
//
lib.parseExcelDate = function (excelSerialDate) {
  // "Excel serial date" is just
  // the count of days since `01/01/1900`
  // (seems that it may be even fractional).
  //
  // The count of days elapsed
  // since `01/01/1900` (Excel epoch)
  // till `01/01/1970` (Unix epoch).
  // Accounts for leap years
  // (19 of them, yielding 19 extra days).
  const daysBeforeUnixEpoch = 70 * 365 + 19;

  // An hour, approximately, because a minute
  // may be longer than 60 seconds, see "leap seconds".
  const hour = 60 * 60 * 1000;

  // "In the 1900 system, the serial number 1 represents January 1, 1900, 12:00:00 a.m.
  //  while the number 0 represents the fictitious date January 0, 1900".
  // These extra 12 hours are a hack to make things
  // a little bit less weird when rendering parsed dates.
  // E.g. if a date `Jan 1st, 2017` gets parsed as
  // `Jan 1st, 2017, 00:00 UTC` then when displayed in the US
  // it would show up as `Dec 31st, 2016, 19:00 UTC-05` (Austin, Texas).
  // That would be weird for a website user.
  // Therefore this extra 12-hour padding is added
  // to compensate for the most weird cases like this
  // (doesn't solve all of them, but most of them).
  // And if you ask what about -12/+12 border then
  // the answer is people there are already accustomed
  // to the weird time behaviour when their neighbours
  // may have completely different date than they do.
  //
  // `Math.round()` rounds all time fractions
  // smaller than a millisecond (e.g. nanoseconds)
  // but it's unlikely that an Excel serial date
  // is gonna contain even seconds.
  //
  return new Date(Math.round((excelSerialDate - daysBeforeUnixEpoch) * 24 * hour) + 12 * hour);
};
katamfetamina
źródło
0

Aby nadrobić zaległości w czasie letnim (od ostatniej niedzieli marca do ostatniej niedzieli października) musiałem zastosować następującą formułę:

=IF(
  AND(
    A2>=EOMONTH(DATE(YEAR(A2);3;1);0)-MOD(WEEKDAY(EOMONTH(DATE(YEAR(A2);3;1);0);11);7);
    A2<=EOMONTH(DATE(YEAR(A2);10;1);0)-MOD(WEEKDAY(EOMONTH(DATE(YEAR(A2);10;1);0);11);7)
  );
  (A2-DATE(1970;1;1)-TIME(1;0;0))*24*60*60*1000;
  (A2-DATE(1970;1;1))*24*60*60*1000
)

Szybkie wyjaśnienie:

Jeśli data [„A2”] przypada między ostatnią niedzielą marca a ostatnią niedzielą października [trzecia i czwarta linijka kodu], odejmę jedną godzinę [-TIME (1; 0; 0)] do daty.

João
źródło