Преобразование SQL-запроса в C # (SQL-запрос преобразует код base36 в DateTime) - PullRequest
1 голос
/ 01 октября 2019

Я бы хотел иметь возможность кодировать \ декодировать идентификаторы, содержащие дату и время, в конфигурации из 7 цифр \ base36, но, несмотря на наличие запроса SQL, который декодирует идентификаторы, до сих пор не повезло.

IУ меня есть SQL-запрос, который может преобразовать код в дату.

Используя следующие идентификаторы, я надеюсь получить соответствующие даты и времени.

    id          Date Time
    ------------------------------------
    A7LXZMM     2004-02-02 09:34:47.000
    KWZKXEX     2018-11-09 11:15:46.000
    LIZTMR9     2019-09-13 11:49:46.000

Запрос:

DECLARE @xdate DATETIME, @offset INT
DECLARE @recid VARCHAR(20)

SET @recid = 'KWZKXEX'
SET @offset = (SELECT DATEDIFF(ss, GETUTCDATE(), GETDATE())) /************* Number of hours offset from GMT ************/

SELECT 
    DATEADD(ss, @offset +
                (POWER(CAST(36 AS BIGINT), 6) *
                 CASE
                    WHEN (SELECT ISNUMERIC(SUBSTRING(@recid, 1, 1))) = 0
                       THEN (SELECT ASCII(SUBSTRING(@recid, 1, 1))) - 55
                       ELSE (SELECT ASCII(SUBSTRING(@recid, 1, 1))) - 48
                 END +
                 POWER(CAST(36 AS BIGINT), 5) *
    case
    when(select isnumeric(substring(@recid,2,1))) = 0
    then(select ascii(substring(@recid,2,1))) - 55
    else (select ascii(substring(@recid,2,1))) - 48
    End
    +
    POWER(cast(36 as bigint),4) *
    case
    when(select isnumeric(substring(@recid,3,1))) = 0
    then(select ascii(substring(@recid,3,1))) - 55
    else (select ascii(substring(@recid,3,1))) - 48
    End
    +
    POWER(cast(36 as bigint),3) *
    case
    when(select isnumeric(substring(@recid,4,1))) = 0
    then(select ascii(substring(@recid,4,1))) - 55
    else (select ascii(substring(@recid,4,1))) - 48
    End
    +
    POWER(cast(36 as bigint),2) *
    case
    when(select isnumeric(substring(@recid,5,1))) = 0
    then(select ascii(substring(@recid,5,1))) - 55
    else (select ascii(substring(@recid,5,1))) - 48
    End
    +
    POWER(cast(36 as bigint),1) *
    case
    when(select isnumeric(substring(@recid,6,1))) = 0
    then(select ascii(substring(@recid,6,1))) - 55
    else (select ascii(substring(@recid,6,1))) - 48
    End
    +
    POWER(cast(36 as bigint),0) *
    case
    when(select isnumeric(substring(@recid,7,1))) = 0
    then(select ascii(substring(@recid,7,1))) - 55
    else (select ascii(substring(@recid,7,1))) - 48
    End
    )
    /50
    ,'1/1/1990')
using System;
using System.Globalization;         
using System.Text;
using System.Numerics;

public class Program
{
    public static void Main()
    {

        string sRecid = "A7LXZMM";
        char c0 = sRecid[0];
        char c1 = sRecid[1];
        char c2 = sRecid[2];
        char c3 = sRecid[3];
        char c4 = sRecid[4];
        char c5 = sRecid[5];
        char c6 = sRecid[6];

        double d6, d5, d4, d3, d2, d1, d0, dsecs;

        Console.WriteLine("c0 = " + c0.ToString());
Console.WriteLine();

        d6 = Math.Pow(36, 6) * ((Char.IsNumber(c0)) ? (byte)c0 - 55 : (byte)c0 - 48);
        d5 = Math.Pow(36, 5) * ((Char.IsNumber(c1)) ? (byte)c1 - 55 : (byte)c1 - 48);
        d4 = Math.Pow(36, 4) * ((Char.IsNumber(c2)) ? (byte)c2 - 55 : (byte)c2 - 48);
        d3 = Math.Pow(36, 3) * ((Char.IsNumber(c3)) ? (byte)c3 - 55 : (byte)c3 - 48);
        d2 = Math.Pow(36, 2) * ((Char.IsNumber(c4)) ? (byte)c4 - 55 : (byte)c4 - 48);
        d1 = Math.Pow(36, 1) * ((Char.IsNumber(c5)) ? (byte)c5 - 55 : (byte)c5 - 48);
        d0 = Math.Pow(36, 0) * ((Char.IsNumber(c6)) ? (byte)c6 - 55 : (byte)c6 - 48);


        dsecs = d6 + d5 + d4 +  d3 +  d2 +  d1 +  d0 / 50;

        DateTime dt = new DateTime(1990, 1, 1, 0, 0, 0,0, System.DateTimeKind.Utc);
        dt =  dt.AddSeconds( dsecs ).ToLocalTime();

    Console.WriteLine("d6 = " + d6.ToString());
    Console.WriteLine("d5 = " + d5.ToString());
    Console.WriteLine("d4 = " + d4.ToString());
    Console.WriteLine("d3 = " + d3.ToString());
    Console.WriteLine("d2 = " + d2.ToString());
    Console.WriteLine("d1 = " + d1.ToString());
    Console.WriteLine("d0 = " + d0.ToString());
    Console.WriteLine("dsecs = " + dsecs.ToString());
    Console.WriteLine("dt = " + dt.ToString());
    }
}

Когда я использую следующие идентификаторы в SQL, я получаю следующие даты.

    id          Date Time
    ------------------------------------
    A7LXZMM     2004-02-02 09:34:47.000
    KWZKXEX     2018-11-09 11:15:46.000
    LIZTMR9     2019-09-13 11:49:46.000

К сожалению, мое "#" преобразование "C" крайне неточно.

Любые предложения относительно того, где я иду не так?

1 Ответ

2 голосов
/ 01 октября 2019

у вас есть проверки Char.IsNumber ... в вашем коде C # по сравнению с вашим скриптом SQL.

В вашем SQL вы вычитаете 55, если символ не число и 48 в противном случае.

В своем коде C # вы вычитаете 55, если символ равен числу, и 48 в противном случае.

Вы тоже не правильно рассчитываете dsecs Я не думаю. Вам нужно добавить от d6 до d0, а затем разделить на 50. Теперь у вас получится разделить d0 на 50, а затем добавить все остальные dn переменные.

Другими словами ...

dsecs = d6 + d5 + d4 + d3 + d2 + d1 + d0 / 50;

Должно быть

dsecs = (d6 + d5 + d4 + d3 + d2 + d1 + d0) / 50;

...