Fecha de Excel a marca de tiempo de Unix

85

¿Alguien sabe cómo convertir una fecha de Excel en una marca de tiempo correcta de Unix?

Hagbard
fuente
¿Qué quieres decir con una "fecha de Excel"? ¿Quiere decir texto formateado como una cadena de fecha y hora legible por humanos como "11/09/2009 3:23:24 PM"?
Matt Ball
4
No olvide que el 19 de enero de 2038, la marca de tiempo de Unix dejará de funcionar debido a un desbordamiento de 32 bits. Antes de este momento, millones de aplicaciones necesitarán adoptar una nueva convención para las marcas de tiempo o migrar a sistemas de 64 bits, lo que comprará la marca de tiempo un "poco" más de tiempo.
13
más como 32 bits más tiempo.
user606723

Respuestas:

107

Ninguno de estos funcionó para mí ... cuando volví la marca de tiempo, faltan 4 años.

Esto funcionó perfectamente: =(A2-DATE(1970,1,1))*86400

El crédito es para: Filip Czaja http://fczaja.blogspot.ca

Publicación original: http://fczaja.blogspot.ca/2011/06/convert-excel-date-into-timestamp.html

Cybercampbell
fuente
6
No olvide su zona horaria (a menos que esté en UTC y no observe el horario de verano). La época de UNIX es independiente de la zona horaria, mientras que las hojas de cálculo no lo son. Aquí hay una guía con ejemplos.
Adam Katz
GMT + 8:=((A1+28800)/86400)+25569
Ivan Chau
hora actual para CDT (horario de verano central):=(NOW()-DATE(1970,1,1))*86400 + 5*3600
hBrent
Las versiones modernas de Excel se quejarán de la fórmula anterior a menos que reemplace las comas con punto y coma:(1970;1;1)
José Luis Blanco
1
@tonygil Funcionará si las celdas a las que se dirige son en realidad fechas en Excel. Si es texto que se supone que representa una fecha, todas las apuestas están canceladas.
Casey
75

Windows y 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 referencia:

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
fuente
3
Office 2011 en Mac parece funcionar bien con la versión "Windows" de estas fórmulas. Las versiones para "Mac" están muy lejos.
radicando
1
Creo que ha invertido las marcas de tiempo de Excel y Unix en esas fórmulas. La marca de tiempo de Unix es un número de segundos, por lo que debe dividirse entre 86400, en lugar de la marca de tiempo de Excel, que es lo que dicen las fórmulas. Vea la respuesta de @ radicand.
Mike Houston
Gracias por los comentarios, probé esto en Mac Excel 2011 y parece que son iguales a la versión de Windows.
Jeff Wu
¿Hay alguna manera de transformar una marca de tiempo de Unix en milisegundos a fecha y hora, conservando los milisegundos?
Lorenzo Belli
dice el hombre de stackoverflow. sí, ¿qué pasa con los segundos intercalares, profesor?
Catamphetamine
11

Si asumimos que la fecha en Excel está en la celda A1 formateada como Fecha y la marca de tiempo de Unix debe estar en una celda A2 formateada como número, la fórmula en A2 debe ser:

= (A1 * 86400) - 2209075200

dónde:

86400 es el número de segundos del día 2209075200 es el número de segundos entre 1900-01-01 y 1970-01-01, que son las fechas base para las marcas de tiempo de Excel y Unix.

Lo anterior es cierto para Windows. En Mac, la fecha base en Excel es 1904-01-01 y el número de segundos debe corregirse a: 2082844800

Grendler
fuente
No funciona exactamente en Windows al menos. Está apagado a las 19 horas.
LLBBL
4
Entonces debería ser esto: = (A1 * 86400) - 2209143600
LLBBL
2
La base de fechas predeterminada de Mac Excel es 1904 mientras que en Windows Excel es 1900, pero puede cambiar la base de fechas en Mac Excel desmarcando "usar el sistema de fechas 1904" en preferencias / cálculo, entonces funciona como Windows Excel.
Cloudranger
6

Aquí hay un mapeo de referencia, asumiendo UTC para sistemas de hojas de cálculo como 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" es 1899/12/31; consulte la sección de errores a continuación. Excel 2011 para Mac (y versiones anteriores) usa el sistema de fechas 1904 .

 

Como suelo utilizar awkpara procesar CSV y contenido delimitado por espacios, desarrollé una forma de convertir la época de UNIX al formato de fecha de Excel apropiado para la zona horaria / 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
}'

Usé echopara este ejemplo, pero puede canalizar un archivo donde la primera columna (para la primera celda en formato .csv, llámelo como awk -F,) es una época UNIX. Modifique $1para representar el número de columna / celda deseado o utilice una variable en su lugar.

Esto realiza una llamada del sistema a date. Si tiene la versión GNU de manera confiable, puede eliminar el 2>/dev/null || date … +%%zy el segundo , $1. Dado lo común que es GNU, no recomendaría asumir la versión de BSD.

El getlinelee el desplazamiento de zona horaria emitida por date +%zen tz, que luego se traduce en hours. El formato será como -0700( PDT ) o +0530( IST ), por lo que la primera subcadena extraída es 07o 05, la segunda es 00o 30(luego dividida por 60 para expresarse en horas), y el tercer uso de tzve si nuestro desplazamiento es negativo y altera hourssi es necesario.

La fórmula dada en todas las otras respuestas en esta página se usa para establecer excel, con la adición del ajuste de zona horaria consciente del horario de verano como hours/24.

Si tiene una versión anterior de Excel para Mac, deberá usarla 24107en lugar de 25569(consulte la asignación anterior).

Para convertir cualquier tiempo arbitrario que no sea de época en tiempos compatibles con Excel con fecha 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 es básicamente el mismo código, pero date -dya no tiene una @para representar la época de Unix (dado lo capaz que es el analizador de cadenas, me sorprende que @sea ​​obligatorio; ¿qué otro formato de fecha tiene 9-10 dígitos?) Y ahora se pregunta para dos salidas: la época y el desplazamiento de zona horaria. Por lo tanto, podría utilizar, por ejemplo, @1234567890como entrada.

Insecto

Lotus 1-2-3 (el software de hoja de cálculo original) trató intencionalmente 1900 como un año bisiesto a pesar de que no lo era (esto redujo la base de código en un momento en el que contaba cada byte). Microsoft Excel retuvo este error por compatibilidad, omitiendo el día 60 (el ficticio 1900/02/29), conservando la asignación de Lotus 1-2-3 del día 59 al 1900/02/28. LibreOffice, en cambio, asignó el día 60 a 1900/02/28 y retrasó todos los días anteriores.

Cualquier fecha anterior al 01/03/1900 podría ser hasta un día libre:

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 no reconoce fechas negativas y tiene una definición especial del cero de enero (31/12/1899) para el día cero. Internamente, Excel sí maneja fechas negativas (después de todo son solo números), pero las muestra como números ya que no sabe cómo mostrarlas como fechas (ni puede convertir fechas más antiguas en números negativos). El 29 de febrero de 1900, un día que nunca sucedió, es reconocido por Excel pero no por LibreOffice.

Adam Katz
fuente
3

Debido a que mis ediciones de lo anterior fueron rechazadas (¿alguno de ustedes realmente lo intentó?), Esto es lo que realmente necesita para que esto funcione:

Windows (y Mac Office 2011+):

  • Marca de tiempo de Unix = (Excel Timestamp - 25569) * 86400
  • Marca de tiempo de Excel = (Unix Timestamp / 86400) + 25569

MAC OS X (antes de Office 2011):

  • Marca de tiempo de Unix = (Excel Timestamp - 24107) * 86400
  • Marca de tiempo de Excel = (Unix Timestamp / 86400) + 24107
radicando
fuente
2

Aparentemente estás fuera de lugar por un día, exactamente 86400 segundos. Use el número 2209161600 No el número 2209075200 Si busca en Google los dos números, encontrará soporte para lo anterior. Probé su fórmula pero siempre aparecía 1 día diferente de mi servidor. No es obvio a partir de la marca de tiempo de Unix a menos que piense en Unix en lugar de tiempo humano ;-) pero si revisa dos veces, verá que esto podría ser correcto.

marca
fuente
Esto es correcto, debido a que Excel calcula el primer año como un año bisiesto aunque no lo sea.
ANisus
Puedo confirmar que el número mágico es 2209161600, siendo 1970-01-01 - 1900-01-01 + 1 día * 86400. Si ingresa 1900-01-01 en Excel y guarde como formato sylk y mire el archivo en un editor de texto, verá que guarda esa fecha como 1 en lugar de cero como debería, por lo que debe agregar 1 día
Cloudranger
1

Tenía una antigua base de datos de Excel con fechas "legibles por humanos", como 2010.03.28 20:12:30. Estas fechas estaban en UTC + 1 (CET) y necesitaba convertirlas en tiempo de época.

Utilicé el = (A4-FECHA (1970; 1; 1)) * 86400 hasta 3600 fórmula para convertir las fechas en cuando época de la columna de A a valores de la columna B. Verifique el desplazamiento de su zona horaria y haga un cálculo con él. 1 hora son 3600 segundos.

La única razón por la que escribo aquí una respuesta, puede ver que este tema tiene más de 5 años es que utilizo las nuevas versiones de Excel y también las publicaciones rojas en este tema, pero son incorrectas. La FECHA (1970; 1; 1). Aquí es necesario separar los años 1970 y enero; y no con,

Si también está experimentando este problema, espero que le ayude. Que tengas un buen día :)

Sorbán Béla
fuente
0

Ninguna de las respuestas actuales funcionó para mí porque mis datos estaban en este formato desde el lado de Unix:

2016-02-02 19:21:42 UTC

Necesitaba convertir esto a Epoch para permitir hacer referencia a otros datos que tenían marcas de tiempo de época.

  1. Cree una nueva columna para la parte de la fecha y analice con esta fórmula

    =DATEVALUE(MID(A2,6,2) & "/" & MID(A2,9,2) & "/" & MID(A2,1,4)) 
    
  2. Como ya ha dicho otro Grendler aquí, cree otra columna

    =(B2-DATE(1970,1,1))*86400 
    
  3. Cree otra columna con solo el tiempo sumado para obtener los segundos totales:

    =(VALUE(MID(A2,12,2))*60*60+VALUE(MID(A2,15,2))*60+VALUE(MID(A2,18,2)))
    
  4. Cree una última columna que solo agregue las dos últimas columnas juntas:

    =C2+D2
    
Dranyar
fuente
0

Aquí está mi respuesta definitiva a esto.

Además, aparentemente, el new Date(year, month, day)constructor de JavaScript no tiene en cuenta los segundos intercalares.

// 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);
};
catanfetamina
fuente
0

Para compensar el horario de verano (desde el último domingo de marzo hasta el último domingo de octubre) tuve que usar la siguiente 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
)

Explicación rápida:

Si la fecha ["A2"] está entre el último domingo de marzo y el último domingo de octubre [tercera y cuarta líneas de código], restaré una hora [-TIME (1; 0; 0)] a la fecha.

João
fuente