从 Unix 日期获取年份 DATEPART

Tom*_*Tom 5 sql-server-2008 sql-server date-format format date

在我的数据库中,日期保留为自 1970 年 1 月 1 日起/之前经过的天数,我认为这是一种 Unix 日期格式,例如。今天是 2018 年 5 月 23 日,值为 17674。

我正在尝试select针对日期表中的列运行语句以仅显示年份。

如果我运行这个:

datepart(year, c.cko_date)
Run Code Online (Sandbox Code Playgroud)

我得到的日期是 1940 年代(应该是最近几年)。

当我跑

select datepart(year, getdate()) 
Run Code Online (Sandbox Code Playgroud)

它正确地告诉我日期是 2018 年。

关于我做错了什么的任何建议?

Han*_*non 6

假设该列是一个int,而不是一个varchar列,您可以这样做:

datepart(year, c.cko_date + 25567)
Run Code Online (Sandbox Code Playgroud)

25567 是 1900-01-01 和 1970-01-01 之间的天数;本质上,这调整了 unix 和 SQL Server 日期时间之间的差异。

SQL Serverdatetime是在 1900-01-01 左右设计的,是“时代”。将 SQL Server 日期视为表示 1900 年 1 月 1 日之前或之后的时间量的十进制值可能会有所帮助。时间是小数部分,例如午夜为 0.0,中午为 0.5,下午 6 点为 0.75。可以存储在datetime列中的值的有效范围是1753-01-01 00:00:00to 9999-01-01 23:59:59.997。在数字上,这对应于从 开始到-53690.0000000结束的范围2958463.99999998

Unix 使用1970-01-01 00:00:00作为它的时代。按照惯例,纪元以通用协调时间或 UTC 开始。对于北美,中部夏令时时区比 UTC 晚 5:00 小时。因此,要将值从 Unix 纪元时间值准确转换为CDT 中的日期时间值需要针对 5 小时的差异进行调整。因此,从以天数表示的 Unix 时间转换的稍微更准确的示例是:

--declare an integer representing the number of days since 1970-01-01
DECLARE @days_since_unix_epoch int = 17674; --2018-05-23
--show the datetime value in UTC
SELECT UTC = CONVERT(datetime, @days_since_unix_epoch + 25567)
--show the datetime value in North American CDT
   , CDT = CONVERT(datetime, @days_since_unix_epoch + 25567) - CONVERT(datetime, '05:00:00');
Run Code Online (Sandbox Code Playgroud)

结果:

?????????????????????????????????????????????????????? ???
? 世界标准时间 ?CDT ?
?????????????????????????????????????????????????????? ???
? 2018-05-23 00:00:00.000 ?2018-05-22 19:00:00.000 ?
?????????????????????????????????????????????????????? ???

虽然我们是技术人员,但通常 Unix 纪元存储为自 以来的毫秒数1970-01-01 00:00:00,而不是天数。如果需要考虑极端精度,则毫秒数可能很难处理,因为自 1970 年以来已经对时间进行了多次调整以处理闰秒。根据我刚刚链接到的维基百科文章,自 1972 年以来,时间增加了 26 个一秒;要准确处理 1970 年到今天之间的日期,您需要在 0 到 26 秒之间适当添加。我不确定 SQL Server 的datetime结构是否准确理解这些调整。

另请注意,SQL Server 的datetime结构具有 3 毫秒的分辨率。考虑以下:

SELECT [1ms] = CONVERT(datetime, '2018-05-22 00:00:00.001')
     , [2ms] = CONVERT(datetime, '2018-05-22 00:00:00.002')
     , [3ms] = CONVERT(datetime, '2018-05-22 00:00:00.003')
Run Code Online (Sandbox Code Playgroud)

输出:

?????????????????????????????????????????????????????? ?????????????????????????????????
? 1 毫秒?2 毫秒?3 毫秒?
?????????????????????????????????????????????????????? ?????????????????????????????????
? 2018-05-22 00:00:00.000 ?2018-05-22 00:00:00.003 ?2018-05-22 00:00:00.003 ?
?????????????????????????????????????????????????????? ?????????????????????????????????

如果您需要更好的分辨率,您应该考虑使用datetime2数据类型,因为它支持微秒精度,以及可能更大范围的日期和时间:

日期范围:0001-01-01 到 9999-12-31
时间范围:00:00:00 到 23:59:59.9999999