Как работает функция преобразования SQL при преобразовании datetime в float?
почему этот вопрос:
declare @currentDate as datetime
set @currentDate ='01/07/2010'
select convert(float, @currentdate)
... - 40183?
Итак, для тех, кто запутывается в моем вопросе, мой вопрос: как узнать результат вышеуказанного запроса, не выполнив его?
Ответы
Ответ 1
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.190000 00:00:00 и 01/07/2010 00:00:00
Уточнение: системы, подобные Unix, используют другой подход для хранения данных: секунды с момента Unix (1 января 1970 года 00:00:00 UTC), который более известен как время эпохи.
[Изменить]
Формат даты этого ответа был изменен на формат YYYYMMDD на 20140416, после нескольких лет опыта работы с SQL Server (и, как сказал @Damien в своем комментарии) это единственный безопасный формат.
Ответ 2
Значения DateTime фактически хранятся в виде двух четырехбайтовых целых чисел под капотом. Первое четырехбайтовое целое число представляет количество дней с 1900-01-01. Второе четырехбайтовое целое число хранится в миллисекундах с полуночи. Когда вы конвертируете datetime в float, десятичная часть представляет процент от прошедшего 24-дневного периода. Таким образом, 0,5 представляет собой полдень.
Ответ 3
В основном это преобразование datetime
в дату OLE. В документации для System.DateTime.ToOADate()
есть достойное описание процесса:
http://msdn.microsoft.com/en-us/library/system.datetime.tooadate.aspx
Быстрое объяснение состоит в том, что целая часть - это количество дней с 12/30/1899. Дробная часть (нуль в этом случае) - это время, деленное на 24.
Ответ 4
Это поможет вам понять реализацию 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 теряет точность на последней миллисекундовой цифре.