【问题标题】:how to cast the hexadecimal to varchar(datetime)?如何将十六进制转换为 varchar(datetime)?
【发布时间】:2011-06-24 04:41:37
【问题描述】:

我导出的日期时间是“CAST(0x0000987C00000000 AS DateTime)”但是当我想把它恢复到日期时间时。它是一个空值。我怎样才能让它再次到日期时间。

【问题讨论】:

  • 您期望从中得到什么样的日期时间值?不确定我是否理解。
  • 天哪……你是怎么得出这个十六进制值的?
  • 在 SQL Server 中为我返回 2006-11-17 00:00:00.000。您是否尝试在 MySQL 中使用 SQL Server 二进制格式?不知道为什么要这样做,但无论如何它被存储为 2 个整数,前 4 个字节是自 1900 年 1 月 1 日以来的天数,第二个字节是自午夜以来的滴答数(每个滴答为 0.33 毫秒)
  • 我怎样才能得到 2006-11-17?因为,我在 mysql 中使用它,但它返回 null。
  • 你可以使用SELECT cast('1900-01-01 00:00:00' + INTERVAL CAST(0x0000987C AS SIGNED) DAY + INTERVAL CAST(0x00000000 AS SIGNED)/300 second as datetime)

标签: mysql sql sql-server postgresql datetime


【解决方案1】:

对于那些在 C# 中寻找解决方案的人。例如,在读取脚本数据库数据时。

        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);

这里我使用了正则表达式,因为我的输入格式如下“CAST(0x0000A53E00E1A17B AS DateTime)”,但是您可以使用 SubString() 或其他任何方法来获取 DateTime 字符串。

【讨论】:

    【解决方案2】:

    日期和日期时间的 MSSQL 十六进制代码不同。

    对于像 0x00000000 这样的日期,您可以使用这个 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;
    

    那就试试

    select convertedata('0x0E360B00')
    

    【讨论】:

      【解决方案3】:

      使用notepad++正则替换

      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)
      

      这将取代

      CAST(0x0000A26900F939A8 AS DateTime)
      

      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), 
      

      【讨论】:

        【解决方案4】:

        这是我做的一个 Java 程序。

        程序扫描给定的文件(在下面的代码中更改名称)

        CAST(0x... AS DateTime)
        

        并用它们各自的替换它们

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

        .

        例如,考虑到SELECT CAST (0x00009CEF00A25634 as datetime) 返回2009-12-30 09:51:03.000,程序会扫描文件中的CAST(0x00009CEF00A25634 AS DateTime) 并将它们替换为CAST('2009-12-30 09:51:03.000' AS DateTime)

        我用它把一个 SQL Server 生成的脚本转换成一个 H2 嵌入式数据库可以理解的东西。

        虽然它对我来说效果很好,但我建议您在使用实际数据之前检查它(只需在一些测试数据上运行并查看)。

        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());
            }
        }
        

        【讨论】:

          【解决方案5】:

          这与 PostgreSQL 的选择语句相同:

          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);
          

          PostgreSQL bit(32) 值必须以 'x' 值而不是 0 开头。

          【讨论】:

          【解决方案6】:

          并没有真正添加任何未说明的内容,但我使用它从上述代码创建了一个 MySql 函数。然后,我可以使用 RegEx 查找和替换(在 Notepad++ 中)将 CAST(0xblahblahblah AS DATETIME) 替换为 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);
          

          【讨论】:

          • 正是我需要帮助将某些东西从 SiteFinity 转换为 WordPress。谢谢!
          【解决方案7】:

          这看起来像 SQL Server datetime 格式。这在内部存储为 2 个整数,前 4 个字节是自 1900 年 1 月 1 日以来的天数,第二个字节是自午夜以来的滴答数(每个滴答为 1/300 秒)。

          如果你需要在 MySQL 中使用它,你可以这样做

          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
          

          返回

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

          (感谢 Ted Hopp the solution 拆分二进制数据)

          【讨论】:

          • 我的 sqlserver 导出成这种格式(“CAST(0x0000987C00000000 AS DateTime)”),我有更多的将数据日期时间迁移到 mysql 中,我该怎么做。
          • @Martin: SELECT HEX(0x0000987C00000000 & 0xFFFFFFFF), HEX(0x0000987C00000000 >> 32);
          • @Mhcl - 谢谢!知道为什么CAST(substr(BinaryData,1,4) AS SIGNED) 不起作用吗?如果我只是执行 SELECT substr(BinaryData,1,4) 并在 SQL 工作台的 BLOB 查看器中查看它,它看起来与执行 SELECT 0x0000987C 时显示的相同
          • @Mhcl - 当我尝试将其插入我的答案时,它不起作用。 cast(HEX(0x0000987C00000000 >> 32)as signed) 返回 987 它似乎将其视为字符串而不是二进制。有什么想法吗?
          • 我添加了HEX() 只是为了视觉目的。做SELECT cast(0x0000987C00000000 >> 32 as signed);
          猜你喜欢
          • 1970-01-01
          • 2015-09-13
          • 2013-10-08
          • 1970-01-01
          • 1970-01-01
          • 2013-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多