2011-02-09 22 views
8

Tengo la exportación de fecha y hora es "CAST (0x0000987C00000000 AS DateTime)" pero cuando quiero volver a ponerlo en datetime.It es un valor NULL. ¿Cómo puedo llegar a la fecha de nuevo?cómo convertir el hexadecimal a varchar (datetime)?

+0

¿Qué tipo de valor de fecha y hora espera de esto? No estoy seguro de comprender. –

+0

Oh chico ... ¿Cómo se te ocurrió este valor hexadecimal? – Mchl

+0

Devuelve '2006-11-17 00: 00: 00.000' para mí en SQL Server. ¿Estás tratando de usar el formato binario de SQL Server en MySQL? No estoy seguro de por qué querría hacer esto, pero de todos modos se almacena como 2 enteros, siendo los primeros 4 bytes los días desde el 1 de enero de 1900 y el 2 el número de tics desde la medianoche (cada marca es de 0,33 ms) –

Respuesta

11

que se parece al formato de SQL Server datetime. Internamente, esto se almacena como 2 enteros, siendo los primeros 4 bytes los días desde el 1 de enero de 1900 y el 2 el número de tics desde la medianoche (cada marca es 1/300 de segundo).

Si necesita utilizar esto en MySQL que podría hacer

SELECT 
     CAST(
      '1900-01-01 00:00:00' + 
      INTERVAL CAST(CONV(substr(HEX(BinaryData),1,8), 16, 10) AS SIGNED) DAY + 
      INTERVAL CAST(CONV(substr(HEX(BinaryData),9,8), 16, 10) AS SIGNED)* 10000/3 MICROSECOND 
     AS DATETIME) AS converted_datetime 
FROM 
(
SELECT 0x0000987C00000000 AS BinaryData 
UNION ALL 
SELECT 0x00009E85013711EE AS BinaryData 
) d 

devoluciones

converted_datetime 
-------------------------- 
2006-11-17 00:00:00 
2011-02-09 18:52:34.286667 

(Gracias a Ted Hopp para the solution en dividir los datos binarios)

+0

Mi sqlserver exportar a este formato ("CAST (0x0000987C00000000 AS DateTime)") y tengo más datos de migración de fecha y hora en mysql, así que, cómo puedo hacerlo. – Zrot

+0

@Martin: 'SELECCIONE HEX (0x0000987C00000000 & 0xFFFFFFFF), HEX (0x0000987C00000000 >> 32);' – Mchl

+0

@Mhcl - ¡Gracias! ¿Alguna idea de por qué 'CAST (substr (BinaryData, 1,4) AS SIGNED)' no funciona? Si acabo de hacer 'SELECT substr (BinaryData, 1,4)' y lo veo en el visor BLOB en SQL workbench, parece idéntico al que se muestra si lo hago 'SELECT 0x0000987C' –

8

realidad, no añadiendo cualquier cosa que no se haya indicado pero utilicé esto para crear una función MySql a partir del código anterior. Entonces puedo usar un RegEx find y replace (en Notepad ++) para reemplazar el CAST (0xblahblahblah AS DATETIME) con sp_ConvertSQLServerDate (0xblahblahblah).

create function sp_ConvertSQLServerDate(dttm binary(16)) 
returns datetime 
return CAST(
     '1900-01-01 00:00:00' + 
     INTERVAL CAST(CONV(substr(HEX(dttm),1,8), 16, 10) AS SIGNED) DAY + 
     INTERVAL CAST(CONV(substr(HEX(dttm),9,8), 16, 10) AS SIGNED)* 10000/3 MICROSECOND 
AS DATETIME); 
+0

Esto es excelente, gracias. – toxaq

+0

Exactamente lo que necesitaba para ayudar a convertir algo de SiteFinity a WordPress. ¡Gracias! – LOLapalooza

1

Aquí hay un programa de Java que hice.

El programa escanea el archivo dado (el cambio de nombre en el código de abajo) para

CAST(0x... AS DateTime) 

y los reemplaza con su respectiva

CAST('yyyy-MM-dd HH:mm:ss.SSS' AS DateTime) 

.

Por ejemplo, teniendo en cuenta que SELECT CAST (0x00009CEF00A25634 as datetime) vuelve 2009-12-30 09:51:03.000, el programa analiza el archivo para CAST(0x00009CEF00A25634 AS DateTime) y los reemplaza con CAST('2009-12-30 09:51:03.000' AS DateTime).

Lo usé para convertir un script generado por SQL Server en algo que una base de datos incrustada H2 podría entender.

Aunque funcionó bien para mí, te aconsejo que lo consultes (simplemente ejecuta algunos datos de prueba y ve) antes de usar datos reales.

import java.io.*; 
import java.text.*; 
import java.util.*; 
import java.util.regex.*; 

public class ReplaceHexDate { 

    public static void main(String[] args) throws Exception { 
     String inputFile = "C:/input.sql"; 
     String inputEncoding = "UTF-8"; 
     String outputFile = "C:/input-replaced.sql"; 
     String outputEncoding = "UTF-8"; 

     BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), inputEncoding)); 
     BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), outputEncoding)); 

     String line; 
     while ((line = br.readLine()) != null) { 
      if (line.indexOf("CAST(0x") > -1) { 
       bw.write(replaceHexWithDate(line)); 
      } else { 
       bw.write(line); 
      } 
      bw.newLine(); 
     } 
     br.close(); 
     bw.flush(); 
     bw.close(); 
    } 

    private static String replaceHexWithDate(String sqlLine) throws ParseException { 
     Pattern castPattern = Pattern.compile("(CAST\\()(0x[A-Fa-f0-9]{16})(AS DateTime\\))"); 
     Matcher m = castPattern.matcher(sqlLine); 
     while (m.find()) { 
      String s = m.group(2); 
      sqlLine = sqlLine.replace(s, "'"+sqlServerHexToSqlDate(s)+"'"); 
     } 
     return sqlLine; 
    } 

    public static String sqlServerHexToSqlDate(String hexString) throws ParseException { 
     String hexNumber = hexString.substring(2); // removes the leading 0x 
     String dateHex = hexNumber.substring(0, 8); 
     String timeHex = hexNumber.substring(8, 16); 

     long daysToAdd = Long.parseLong(dateHex, 16); 
     long millisToAdd = (long) (Long.parseLong(timeHex, 16) *10/3); 

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 

     Calendar startingCal = Calendar.getInstance(); 
     String startingDate = "1900-01-01 00:00:00.000"; 
     startingCal.setTime(sdf.parse(startingDate)); 

     Calendar convertedCal = Calendar.getInstance(); 
     convertedCal.setTime(sdf.parse(startingDate)); 
     convertedCal.add(Calendar.DATE, (int) daysToAdd); 
     convertedCal.setTimeInMillis(convertedCal.getTimeInMillis() + millisToAdd); 

     return sdf.format(convertedCal.getTime()); 
    } 
} 
2

Ésta es la misma instrucción de selección para PostgreSQL:

(32) los valores
SELECT '1900-01-01 00:00:00'::date + 
    (('x'||substring(x::text,3,8))::bit(32)::int::text||'days')::interval + 
    ((('x'||substring(x::text,11,8))::bit(32)::int /300)::text||' seconds')::interval 
FROM (VALUES 
    ('0x00009fff00e24076'), 
    ('0x00009ff10072d366'), 
    ('0x00009ff10072ce3a'), 
    ('0x00009ff10072c5e2'), 
    ('0x00009ff10072bc3c')) as x(x); 

bits PostgreSQL tienen que empezar con el valor 'x' en lugar de 0.

+0

Esta pregunta está etiquetada MySql. Considere agregar esta respuesta a http://stackoverflow.com/q/7580700/73226 –

1

Usando Notepad ++ expresiones regulares reemplace

cast[(]0x([0-9A-F]{16}) As DateTime[)] 

CAST('1900-01-01 00:00:00' + INTERVAL CAST(CONV(substr(HEX(0x\1),1,8), 16, 10) AS SIGNED) DAY + INTERVAL CAST(CONV(substr(HEX(0x\1),9,8), 16, 10) AS SIGNED)* 10000/3 MICROSECOND AS DATETIME) 

Esto reemplazará

CAST(0x0000A26900F939A8 AS DateTime) 

a

CAST('1900-01-01 00:00:00' + INTERVAL CAST(CONV(substr(HEX(0x0000A26900F939A8),1,8), 16, 10) AS SIGNED) DAY + INTERVAL CAST(CONV(substr(HEX(0x0000A26900F939A8),9,8), 16, 10) AS SIGNED)* 10000/3 MICROSECOND AS DATETIME), 
0

código hexadecimal MSSQL para la fecha y fechaHora son diferentes.

Para la fecha en fomate como 0x00000000 puede utilizar esta función postgres:

CREATE FUNCTION convertedata(text) RETURNS timestamp without time zone 
as $$ SELECT '0001-01-01 00:00:00'::date + (('x'|| 
(regexp_replace(
substring($1::text,3,8)::text, 
'(\w\w)(\w\w)(\w\w)(\w\w)', 
'\4\3\2\1'))::text 
)::bit(32)::int::text||'days')::interval $$ 
LANGUAGE SQL; 

continuación, intente

select convertedata('0x0E360B00') 
0

Para aquellos que buscan una solución en C#. Por ejemplo, al leer datos de bases de datos con guiones.

 string pattern = @"CAST\(0x(\w{8})(\w{8}) AS DateTime\)"; 
     Regex r = new Regex(pattern); 
     Match m = r.Match(hex);    

     int d = System.Convert.ToInt32("0x" + m.Groups[1].Value, 16); 
     int t = System.Convert.ToInt32("0x" + m.Groups[2].Value, 16); 

     DateTime converted = new DateTime(1900, 1, 1).AddDays(d).AddSeconds(t/300); 

Aquí he utilizado expresiones regulares desde mi entrada es de la siguiente forma "CAST (AS 0x0000A53E00E1A17B DateTime)", pero se puede utilizar substring() o lo que sea para obtener la cadena de DateTime.