Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
gabryelle
Member

Откуда:
Сообщений: 6
Здравствуйте. Сервер mssql 2008 r2. Существует строка varbinary 0x142B92F20000
142B (0-3 байт) - Идентификатор (не важно)
92F2 (4-7 байт) - дата
0000 (8-11 байт) - время

Методом тыка и тестов я нашел систему:

Исходная дата в формате ГГ-ММ-ДД чч-мм

4 и 5 байты - это год (ГГ). Если месяц четный, пишется прямым текстом в hex (18 год = 12h).
Если месяц нечетный, то прибавляем 128 (80h), итого 18 год = 0x92 hex.

7й байт - это месяц + определитель четности дня
0 - 0/1мес (чет)
1 - 2/3мес (чет)
2 - 4/5мес (чет)
3 - 6/7мес (чет)
4 - 8/9мес (чет)
5 - 10/11мес (чет)
6 - 12/13мес (чет)
7 - 14/15мес (чет)

8 - 0/1мес (нечет)
9 - 2/3мес (нечет)
A - 4/5мес (нечет)
B - 6/7мес (нечет)
C - 8/9мес (нечет)
D - 10/11мес (нечет)
E - 12/13мес (нечет)
F - 14/15мес (нечет)

6й байт - день. Тупо делим на 2 и переводим в hex. Чет/нечет берется с месяца.
30 день = 30/2 = 15 = F hex (для месяца 0-7)
31 день = (31-1)/2 = 15 = F hex (для месяца 8-F)

В качестве времени меня устраивала полночь, поэтому я не стал заморачиваться с разбором, а оставил просто 0000.

В общем та еще головоломка. Подходящей формулы я найти не смог, поэтому в конце 2017 годя я просто составил таблицу на год вперед и сравнивал скриптом значения из нее.

hex dec
+
0x110E 2017-12-01
0x1116 2017-12-02
0x112E 2017-12-03
0x1126 2017-12-04
0x112E 2017-12-05
0x1136 2017-12-06
0x113E 2017-12-07
0x1146 2017-12-08
0x114E 2017-12-09
0x1156 2017-12-10
0x115E 2017-12-11
0x1166 2017-12-12
0x116E 2017-12-13
0x1176 2017-12-14
0x117E 2017-12-15
0x1186 2017-12-16
0x118E 2017-12-17
0x1196 2017-12-18
0x119E 2017-12-19
0x11A6 2017-12-20
0x11AE 2017-12-21
0x11B6 2017-12-22
0x11BE 2017-12-23
0x11C6 2017-12-24
0x11CE 2017-12-25
0x11D6 2017-12-26
0x11DE 2017-12-27
0x11E6 2017-12-28
0x11EE 2017-12-29
0x11F6 2017-12-30
0x11FE 2017-12-31
0x9208 2018-01-01
0x9210 2018-01-02
0x9218 2018-01-03
0x9220 2018-01-04
0x9228 2018-01-05
0x9230 2018-01-06
0x9238 2018-01-07
0x9240 2018-01-08
0x9248 2018-01-09
0x9250 2018-01-10
0x9258 2018-01-11
0x9260 2018-01-12
0x9268 2018-01-13
0x9270 2018-01-14
0x9278 2018-01-15
0x9280 2018-01-16
0x9288 2018-01-17
0x9290 2018-01-18
0x9298 2018-01-19
0x92A0 2018-01-20
0x92A8 2018-01-21
0x92B0 2018-01-22
0x92B8 2018-01-23
0x92C0 2018-01-24
0x92C8 2018-01-25
0x92D0 2018-01-26
0x92D8 2018-01-27
0x92E0 2018-01-28
0x92E8 2018-01-29
0x92F0 2018-01-30
0x92F8 2018-01-31
0x1209 2018-02-01
0x1211 2018-02-02
0x1219 2018-02-03
0x1221 2018-02-04
0x1229 2018-02-05
0x1231 2018-02-06
0x1239 2018-02-07
0x1241 2018-02-08
0x1249 2018-02-09
0x1251 2018-02-10
0x1259 2018-02-11
0x1261 2018-02-12
0x1269 2018-02-13
0x1271 2018-02-14
0x1279 2018-02-15


Естественно, о гибкости тут говорить не приходится. Сейчас появились новые задачи, где было бы полезно использовать любую необходимую дату, а не только 1 день в неделю по таблице, да и год к концу подходит, таблица заканчивается. Может быть кто-то узнает этого зверя и каким образом можно автоматизировать процесс записи даты в varbinary и обратно? Точное время желательно, но без него можно обойтись в принципе, но дата прям очень нужна. Буду благодарен любой помощи с этим.

Сообщение было отредактировано: 31 окт 18, 17:41
31 окт 18, 15:30    [21720455]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
aleks222
Member

Откуда:
Сообщений: 923
Ээх, страдалец.

Чего ты там намудрил с чет-нечет?

92 F2 00 00

всего 4 (четыре) байта или 4*8 бит = 32 бита

16 бит - дата, 16 бит время

7 бит = номер года
4 бит = номер месяца
5 бит = номер дня

Элементарно преобразуется.
1 ноя 18, 10:51    [21721202]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7663
gabryelle,

CLR функцию напишите.
1 ноя 18, 12:54    [21721397]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
gabryelle
Member

Откуда:
Сообщений: 6
aleks222, все равно не понимаю. Вот для примера
0x9270 = 2018-01-14 = 1001001001110000
0x9278 = 2018-01-15 = 1001001001111000
0x1271 = 2018-02-14 = 0001001001110001
0x1279 = 2018-02-15 = 0001001001111001

1 0010010 01110 000
1 0010010 01111 000
0 0010010 01110 001
0 0010010 01111 001

Получается
1 0010010=год 01110=день 000(плюс 16й бит = месяц)
Почему номер месяца так разбросан по краям? И как мне кодировать/декодировать это средствами SQL? Кстати, будет использоваться 17 версия sql (хотя изначально сервер писался под 2008 r2).
Владислав Колосов, насколько я понял, для CLR функции нужно писать библиотеку в Visual Studio, мне такое не по зубам. Если я в хранимках MS SQL еще как-то соображаю, то VS для меня темный лес.

Вот что у меня получилось
declare @mybinary varbinary(2), @myint int, @testbit int
set @mybinary = 0x1279 /*0001 0010 0111 1001*/
set @myint = cast(@mybinary as int)

/*Тут переворачиваем и 16й бит становится 8м (0111 1001 0001 0010)*/
set @testbit = sys.fn_MStestbit(@mybinary, 8) --Проверяем 8 бит

declare @year int, @month int, @day int

set @year = (@myint & 0x7F00)/256 --Обнуляем лишнее и отсекаем 8 бит справа
set @day = (@myint & 0xF8)/8 --Обнуляем лишнее и отсекаем 3 бита справа
set @month = (@myint & 0x07)*2 + @testbit --Обнуляем лишнее, оставляя первые 3 бита, добавляем еще 1 бит справа (16й бит)

select @year as Год, @month as Месяц, @day as День


Что скажете? Есть более подходящие варианты? Или на основе этого буду думать обратное преобразование.
1 ноя 18, 16:09    [21721717]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
gabryelle
Member

Откуда:
Сообщений: 6
Насчет месяца сообразил - если поменять местами первые и последние 8 бит, то все получается:
01110-день 0001-месяц 0010010-год
1 ноя 18, 16:27    [21721746]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31331
gabryelle
aleks222, все равно не понимаю. Вот для примера
Просто байты переставлены, бывает-с, Unix :-)

Если переставить байты, то получается, как написал aleks222
declare @mybinary varbinary(2), @myint int, @testbit int

set @mybinary = 0x1279 /*0001 0010 0111 1001*/
set @myint = convert(int, (substring(@mybinary, 2,1) + substring(@mybinary, 1,1)))
select @mybinary, @myint

declare @year int, @month int, @day int

set @year = (@myint & 0x7F) -- 7 бит справа (младшие)
set @month = (@myint/128) & 0x0F -- следующие 4 бита
set @day = (@myint/2048) & 0x1F -- и потом ещё старшие 5 бит

select @year as Год, @month as Месяц, @day as День
1 ноя 18, 16:46    [21721761]     Ответить | Цитировать Сообщить модератору
 Re: Помогите подобрать формулу для конвертации даты в varbinary по определенному алгоритму  [new]
gabryelle
Member

Откуда:
Сообщений: 6
Все получилось, большое спасибо всем за помощь. Доведу до ума и сделаю из этого хранимую процедуру.
1 ноя 18, 18:41    [21721855]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить