Как работает функция преобразования SQL при преобразовании даты и времени в число с плавающей точкой? - PullRequest
11 голосов
/ 10 ноября 2010

почему выход этого запроса:

declare @currentDate as datetime
    set @currentDate ='01/07/2010'

select convert(float, @currentdate) 

... это 40183?

Так что для тех, кто путается с моим вопросом, мой вопрос: как узнать результат вышеупомянутого запроса без его выполнения?

Ответы [ 4 ]

12 голосов
/ 10 ноября 2010

DateTime часто представляется как число дней с заранее определенной даты (обычно известной как эпоха) в целочисленной части, а процентная доля дня, прошедшего с полуночи, в дробной части.

SQL Server не является исключением из этого, поэтому преобразование во Float имеет большой смысл. День 0 - 01 января 1900 00:00:00 (AFAIK, без определенного часового пояса, поэтому вы должны считать это «местным временем»).

Итак, вы можете попробовать это:

declare @ADate DateTime;
set @ADate = '19000101 00:00:00';
select CONVERT(float, @ADate);  --should print 0
set @ADate = '19000101 12:00:00';
select CONVERT(float, @ADate);  --should print 0.5
set @ADate = '19001231 06:00:00';
select CONVERT(float, @ADate);  --should print 364.25

Итак, для ваших результатов прошло 40183 дня с 01.01.1900 00:00:00 и 01.07.2010 00: 00: 00

Пояснение: Unix-подобные системы используют другой подход для хранения времени: секунды с начала Unix (1 января 1970 г., 00:00:00 UTC), который более известен как время эпохи.

[Изменить] Формат даты в этом ответе был изменен на формат ГГГГММДД на 20140416, после нескольких новых лет работы с SQL Server (и, как сказал @Damien в своем комментарии), это единственный безопасный формат.

4 голосов
/ 10 ноября 2010

Значения DateTime на самом деле хранятся в виде двух четырехбайтовых целых чисел. Первое четырехбайтовое целое число представляет количество дней с 1900-01-01. Второе четырехбайтовое целое число хранит количество миллисекунд с полуночи. Когда вы конвертируете дату и время в число с плавающей точкой, десятичная часть представляет процент прошедших 24 дней. Таким образом, 0,5 представляет полдень.

3 голосов
/ 10 ноября 2010

Это в основном преобразование datetime в дату OLE.В документации есть достойное описание процесса для System.DateTime.ToOADate():

http://msdn.microsoft.com/en-us/library/system.datetime.tooadate.aspx

Быстрое объяснение состоит в том, что целая часть - это количество дней с 30.12.1899.Дробная часть (в данном случае ноль) - это время, деленное на 24.

0 голосов
/ 31 января 2018

Это должно помочь вам понять реализацию TSQL (или реализовать свою собственную):

DECLARE
    @date DATETIME = '20180125 09:15:30.549',
    @date_dec DECIMAL (26,10) = 43123.3857702546

SELECT
    CAST(@date_dec AS DATETIME) AS [TSQL cast to DATETIME],
    CAST(@date AS DECIMAL (26,10)) AS [TSQL cast to DECIMAL]

SELECT
    DATEADD(DAY, FLOOR(@date_dec), 
        DATEADD(HOUR, FLOOR(@date_dec % 1 * 24), 
            DATEADD(MINUTE, FLOOR((@date_dec % 1 * 24) % 1 * 60), 
                DATEADD(SECOND, FLOOR(((@date_dec % 1 * 24) % 1 * 60) % 1 * 60), 
                    DATEADD(MILLISECOND, FLOOR((((@date_dec % 1 * 24) % 1 * 60) % 1 * 60) % 1 * 1000), '19000101')
                )
            )
        )
    ) AS [Manual cast to DATETIME],
    DATEDIFF(DAY, '19000101', @date) 
    + (
        DATEPART(HOUR, @date) 
        + (
            DATEPART(MINUTE, @date) 
            + (
                DATEPART(SECOND, @date)
                + DATEPART(MILLISECOND, @date) / CAST(1000 AS FLOAT)
              ) / CAST(60 AS FLOAT)
          ) / CAST(60 AS FLOAT)
      ) / CAST(24 AS DECIMAL (26,10)) AS [Manual cast to DECIMAL]

Обратите внимание, что результат не всегда совпадает с тем, как TSQL теряет точность для последней цифры миллисекунды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...