Czy ktoś wie, jak przekonwertować datę Excela na poprawny znacznik czasu Unix?
Czy ktoś wie, jak przekonwertować datę Excela na poprawny znacznik czasu Unix?
Odpowiedzi:
Ż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
=((A1+28800)/86400)+25569
=(NOW()-DATE(1970,1,1))*86400 + 5*3600
(1970;1;1)
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)
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
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ą awk
z 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 echo
w 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ń, $1
aby 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 … +%%z
i drugą wersję , $1
. Biorąc pod uwagę, jak powszechne jest GNU, nie polecałbym zakładać wersji BSD.
getline
Czyta przesunięcia strefy czasowej wyprowadzony przez date +%z
się 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 07
lub 05
, drugi to 00
lub 30
(następnie podzielony przez 60 w celu wyrażenia w godzinach), a trzecie użycie tz
sprawdza, czy nasze przesunięcie jest ujemne i zmienia hours
Jeś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ć 24107
zamiast 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 -d
nie 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. @1234567890
Jako wejścia.
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/01
…
59 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.
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+):
(Excel Timestamp - 25569) * 86400
(Unix Timestamp / 86400) + 25569
MAC OS X (przed Office 2011):
(Excel Timestamp - 24107) * 86400
(Unix Timestamp / 86400) + 24107
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.
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 :)
Ż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.
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))
Jak już powiedział inny Grendler, utwórz kolejną kolumnę
=(B2-DATE(1970,1,1))*86400
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)))
Utwórz ostatnią kolumnę, która po prostu dodaje do siebie dwie ostatnie kolumny:
=C2+D2
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);
};
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.
"11/09/2009 3:23:24 PM"
?