Alguém sabe como converter uma data do Excel em um timestamp correto do Unix?
Alguém sabe como converter uma data do Excel em um timestamp correto do Unix?
Respostas:
Nenhum desses funcionou para mim ... quando eu converti o carimbo de data / hora de volta, faltam 4 anos.
Funcionou perfeitamente: =(A2-DATE(1970,1,1))*86400
O crédito vai para: Filip Czaja http://fczaja.blogspot.ca
Postagem original: 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
Para referência:
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 assumirmos que a data no Excel está na célula A1 formatada como Data e o carimbo de data / hora Unix deve estar em uma célula A2 formatada como número, a fórmula em A2 deve ser:
= (A1 * 86400) - 2209075200
Onde:
86400 é o número de segundos no dia 2209075200 é o número de segundos entre 1900-01-01 e 1970-01-01, que são as datas base para os carimbos de data / hora do Excel e Unix.
O acima é verdadeiro para o Windows. No Mac, a data base no Excel é 01/01/1904 e o número dos segundos deve ser corrigido para: 2082844800
Aqui está um mapeamento para referência, assumindo UTC para sistemas de planilhas como o 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
* “Janeiro Zero, 1900” é 1899/12/31; veja a seção Bug abaixo. † Excel 2011 para Mac (e anteriores) usa o sistema de data 1904 .
Como costumo usar awk
para processar CSV e conteúdo delimitado por espaço, desenvolvi uma maneira de converter a época do UNIX em formato de data do Excel adequado para fuso horário / horário de verão :
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
}'
Usei echo
para este exemplo, mas você pode canalizar um arquivo em que a primeira coluna (para a primeira célula no formato .csv, chame-o de awk -F,
) é uma época UNIX. Altere $1
para representar o número da coluna / célula desejada ou use uma variável.
Isso faz uma chamada de sistema para date
. Se você tiver a versão GNU confiável, pode remover o 2>/dev/null || date … +%%z
e o segundo , $1
. Dado o quão comum o GNU é, eu não recomendaria assumir a versão do BSD.
O getline
lê o deslocamento de fuso horário gerado por date +%z
em tz
, que é então convertido em hours
. O formato será como -0700
( PDT ) ou +0530
( IST ), então a primeira substring extraída é 07
ou 05
, a segunda é 00
ou 30
(então dividido por 60 para ser expresso em horas), e o terceiro uso de tz
vê se nosso deslocamento é negativo e altera hours
se necessário.
A fórmula fornecida em todas as outras respostas nesta página é usada para definir excel
, com a adição do ajuste de fuso horário em função do horário de verão como hours/24
.
Se você estiver em uma versão mais antiga do Excel para Mac, precisará usar 24107
no lugar de 25569
(consulte o mapeamento acima).
Para converter qualquer hora arbitrária fora da época em horas compatíveis com o Excel com 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
}'
Este é basicamente o mesmo código, mas date -d
não tem mais um @
para representar a época unix (dada a capacidade do analisador de strings, estou realmente surpreso que @
seja obrigatório; que outro formato de data tem de 9 a 10 dígitos?) E agora é perguntado para duas saídas: a época e o deslocamento de fuso horário. Portanto, você pode usar, por exemplo, @1234567890
como uma entrada.
O Lotus 1-2-3 (o software de planilha original) tratou intencionalmente 1900 como um ano bissexto, apesar do fato de que não foi (isso reduziu a base de código no momento em que cada byte era contado). O Microsoft Excel manteve esse bug para compatibilidade, ignorando o dia 60 (o fictício 1900/02/29), mantendo o mapeamento do Lotus 1-2-3 do dia 59 para 1900/02/28. Em vez disso, o LibreOffice atribuiu o dia 60 a 1900/02/28 e adiou todos os dias anteriores um.
Qualquer data antes de 1900/03/01 pode significar até um dia de folga:
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
O Excel não reconhece datas negativas e tem uma definição especial do Zeroth de janeiro (1899/12/31) para o dia zero. Internamente, o Excel realmente lida com datas negativas (afinal, são apenas números), mas os exibe como números, pois não sabe como exibi-los como datas (nem pode converter datas mais antigas em números negativos). 29 de fevereiro de 1900, um dia que nunca aconteceu, é reconhecido pelo Excel, mas não pelo LibreOffice.
Como minhas edições acima foram rejeitadas (algum de vocês realmente tentou?), Aqui está o que você realmente precisa para fazer isso funcionar:
Windows (e Mac Office 2011+):
(Excel Timestamp - 25569) * 86400
(Unix Timestamp / 86400) + 25569
MAC OS X (antes do Office 2011):
(Excel Timestamp - 24107) * 86400
(Unix Timestamp / 86400) + 24107
Você está aparentemente errado por um dia, exatamente 86400 segundos. Use o número 2209161600 Não o número 2209075200 Se você pesquisar os dois números no Google, encontrará suporte para os anteriores. Tentei sua fórmula mas sempre aparecia 1 dia diferente do meu servidor. Não é óbvio a partir do carimbo de data / hora do Unix, a menos que você pense no Unix ao invés do tempo humano ;-) mas se você verificar novamente, verá que pode estar correto.
Eu tinha um banco de dados Excel antigo com datas "legíveis por humanos", como 2010.03.28 20:12:30 Essas datas estavam em UTC + 1 (CET) e precisava convertê-las para o tempo de época.
I utilizado o = (A4-DATA (1970; 1; 1)) * 86400-3600 fórmula para converter as datas de tempo época a partir da coluna A para os valores da coluna B. Verifique a diferença de fuso horário e faça contas com ela. 1 hora equivale a 3600 segundos.
A única coisa que eu escrevo aqui uma resposta, você pode ver que este tópico tem mais de 5 anos é que eu uso as novas versões do Excel e também posts vermelhos neste tópico, mas eles estão incorretos. A DATE (1970; 1; 1). Aqui, o 1970 e o janeiro precisam ser separados com; e não com,
Se você também estiver enfrentando esse problema, espero que ajude. Tenha um bom dia :)
Nenhuma das respostas atuais funcionou para mim porque meus dados estavam neste formato no lado unix:
2016-02-02 19:21:42 UTC
Eu precisei converter isso para Epoch para permitir a referência de outros dados que tinham timestamps de época.
Crie uma nova coluna para a parte da data e analise com esta fórmula
=DATEVALUE(MID(A2,6,2) & "/" & MID(A2,9,2) & "/" & MID(A2,1,4))
Como outro Grendler já afirmou aqui, crie outra coluna
=(B2-DATE(1970,1,1))*86400
Crie outra coluna apenas com o tempo adicionado para obter o total de segundos:
=(VALUE(MID(A2,12,2))*60*60+VALUE(MID(A2,15,2))*60+VALUE(MID(A2,18,2)))
Crie uma última coluna que apenas adiciona as duas últimas colunas:
=C2+D2
Aqui está minha resposta final para isso.
Aparentemente, o new Date(year, month, day)
construtor do JavaScript também não leva em conta os segundos bissextos.
// 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);
};
Para compensar o horário de verão (começando no último domingo de março até o último domingo de outubro), tive que usar a seguinte fórmula:
=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
)
Explicação rápida:
Se a data ["A2"] for entre o último domingo de março e o último domingo de outubro [terceira e quarta linhas de código], então estarei subtraindo uma hora [-TIME (1; 0; 0)] da data.
"11/09/2009 3:23:24 PM"
?