Qualcuno sa come convertire una data di Excel in un timestamp Unix corretto?
Qualcuno sa come convertire una data di Excel in un timestamp Unix corretto?
Risposte:
Nessuno di questi ha funzionato per me ... quando ho convertito il timestamp sono passati 4 anni.
Funzionava perfettamente: =(A2-DATE(1970,1,1))*86400
Il merito va a: Filip Czaja http://fczaja.blogspot.ca
Post originale: 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 e 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
Per riferimento:
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)
Se assumiamo che la data in Excel sia nella cella A1 formattata come Data e il timestamp Unix dovrebbe essere in una cella A2 formattata come numero, la formula in A2 dovrebbe essere:
= (A1 * 86400) - 2209075200
dove:
86400 è il numero di secondi nel giorno 2209075200 è il numero di secondi tra 1900-01-01 e 1970-01-01 che sono le date di base per i timestamp di Excel e Unix.
Quanto sopra è vero per Windows. Su Mac la data di base in Excel è 1904-01-01 e il numero dei secondi deve essere corretto in: 2082844800
Ecco una mappatura di riferimento, assumendo UTC per sistemi di fogli di calcolo come 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" è il 1899/12/31; vedere la sezione Bug di seguito. † Excel 2011 per Mac (e versioni precedenti) utilizza il sistema di data 1904 .
Poiché utilizzo spesso awkper elaborare CSV e contenuto delimitato da spazi, ho sviluppato un modo per convertire l'epoca UNIX in un formato di data Excel appropriato per fuso orario / DST :
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
}'
Ho usato echoper questo esempio, ma puoi reindirizzare un file in cui la prima colonna (per la prima cella in formato .csv, chiamala come awk -F,) è un'epoca UNIX. Modifica $1per rappresentare il numero di colonna / cella desiderato o utilizza invece una variabile.
Questo fa una chiamata di sistema a date. Se si dispone della versione GNU in modo affidabile, è possibile rimuovere il 2>/dev/null || date … +%%ze il secondo , $1. Dato quanto è comune GNU, non consiglierei di assumere la versione di BSD.
La getlinelegge il fuso orario in uscita dal date +%zin tz, che viene poi tradotto in hours. Il formato sarà come -0700( PDT ) o +0530( IST ), quindi la prima sottostringa estratta è 07o 05, la seconda è 00o 30(quindi divisa per 60 per essere espressa in ore), e il terzo uso di tzvede se il nostro offset è negativo e altera hoursse necessario.
La formula data in tutte le altre risposte in questa pagina viene utilizzata per impostare excel, con l'aggiunta della regolazione del fuso orario in base all'ora legale come hours/24.
Se utilizzi una versione precedente di Excel per Mac, dovrai utilizzarla 24107al posto di 25569(vedi la mappatura sopra).
Per convertire qualsiasi tempo arbitrario non d'epoca in tempi compatibili con Excel con data 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
}'
Questo è fondamentalmente lo stesso codice, ma date -dnon ha più un'epoca @per rappresentare unix (data la capacità del parser di stringhe, in realtà sono sorpreso che @sia obbligatorio; quale altro formato di data ha 9-10 cifre?) E ora viene chiesto per due uscite: l'epoca e l'offset del fuso orario. È quindi possibile utilizzare ad esempio @1234567890come input.
Lotus 1-2-3 (il software del foglio di calcolo originale) considerava intenzionalmente il 1900 come un anno bisestile nonostante il fatto che non lo fosse (questo riduceva la base di codice in un momento in cui ogni byte contava). Microsoft Excel ha mantenuto questo bug per la compatibilità, saltando il giorno 60 (il 1900/02/29 fittizio), mantenendo la mappatura di Lotus 1-2-3 dal giorno 59 al 1900/02/28. LibreOffice ha invece assegnato il giorno 60 al 1900/02/28 e ha spostato indietro di uno tutti i giorni precedenti.
Qualsiasi data prima del 1900/03/01 potrebbe essere fino a un giorno libero:
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 non riconosce le date negative e ha una definizione speciale dello zero di gennaio (1899/12/31) per il giorno zero. Internamente, Excel gestisce effettivamente le date negative (dopotutto sono solo numeri), ma le visualizza come numeri poiché non sa come visualizzarle come date (né può convertire le date più vecchie in numeri negativi). Il 29 febbraio 1900, un giorno che non è mai accaduto, viene riconosciuto da Excel ma non da LibreOffice.
Poiché le mie modifiche a quanto sopra sono state rifiutate (qualcuno di voi ha davvero provato?), Ecco di cosa avete veramente bisogno per farlo funzionare:
Windows (e Mac Office 2011+):
(Excel Timestamp - 25569) * 86400(Unix Timestamp / 86400) + 25569MAC OS X (precedente a Office 2011):
(Excel Timestamp - 24107) * 86400(Unix Timestamp / 86400) + 24107Apparentemente sei fuori di un giorno, esattamente 86400 secondi. Usa il numero 2209161600 Non il numero 2209075200 Se cerchi i due numeri su Google, troverai supporto per quanto sopra. Ho provato la tua formula ma arrivava sempre un giorno diverso dal mio server. Non è ovvio dal timestamp unix a meno che non pensi in unix invece che in tempo umano ;-) ma se controlli due volte vedrai che potrebbe essere corretto.
Avevo un vecchio database Excel con date "leggibili dall'uomo", come 2010.03.28 20:12:30 Queste date erano in UTC + 1 (CET) e dovevo convertirlo in tempo epocale.
Ho usato la formula = (A4-DATE (1970; 1; 1)) * 86400-3600 per convertire le date in tempo dell'epoca dalla colonna A ai valori della colonna B. Controlla la differenza di fuso orario e calcola i calcoli. 1 ora è 3600 secondi.
L'unica cosa per cui scrivo qui una risposta, puoi vedere che questo argomento ha più di 5 anni è che uso le nuove versioni di Excel e anche i post rossi in questo argomento, ma non sono corretti. La DATA (1970; 1; 1). Qui il 1970 e il gennaio vanno separati; e non con
Se stai riscontrando anche questo problema, spero che ti sia d'aiuto. Buona giornata :)
Nessuna delle risposte attuali ha funzionato per me perché i miei dati erano in questo formato dal lato unix:
02-02-2016 19:21:42 UTC
Avevo bisogno di convertirlo in Epoch per consentire il riferimento ad altri dati che avevano timestamp epoch.
Crea una nuova colonna per la parte della data e analizza con questa formula
=DATEVALUE(MID(A2,6,2) & "/" & MID(A2,9,2) & "/" & MID(A2,1,4))
Come altri Grendler hanno già affermato qui, crea un'altra colonna
=(B2-DATE(1970,1,1))*86400
Crea un'altra colonna sommando solo il tempo per ottenere il totale dei secondi:
=(VALUE(MID(A2,12,2))*60*60+VALUE(MID(A2,15,2))*60+VALUE(MID(A2,18,2)))
Crea un'ultima colonna che aggiunge solo le ultime due colonne insieme:
=C2+D2
Ecco la mia risposta definitiva a questo.
Apparentemente anche il new Date(year, month, day)costruttore di javascript non tiene conto dei secondi intercalari.
// 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);
};
Per compensare l' ora legale (a partire dall'ultima domenica di marzo fino all'ultima domenica di ottobre) ho dovuto utilizzare la seguente formula:
=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
)
Spiegazione rapida:
Se la data ["A2"] è compresa tra l'ultima domenica di marzo e l'ultima domenica di ottobre [terza e quarta riga di codice], sottraerò un'ora [-TIME (1; 0; 0)] alla data.
"11/09/2009 3:23:24 PM"?