如何在 SQL Server 中将 bigint(UNIX 时间戳)转换为日期时间?
如何在 SQL Server 中将 UNIX 时间戳 (bigint) 转换为 DateTime?
How can I convert UNIX timestamp (bigint) to DateTime in SQL Server?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
这对我有用:
如果有人想知道为什么 1970-01-01,这被称为纪元时间。
以下是维基百科的引用:
2038 年问题
此外,DateAdd 函数采用
int
来表示要添加的秒数。因此,如果您尝试添加超过2147483647
秒,您将收到算术溢出错误。要解决此问题,您可以将添加分解为两次对 DateAdd 的调用,一次用于年份,一次用于剩余秒数。这将允许您转换代表大于 2038 年的年份的时间戳。
This worked for me:
In case anyone wonders why 1970-01-01, This is called Epoch time.
Below is a quote from Wikipedia:
The Year 2038 Problem
Furthermore the DateAdd function takes an
int
for the seconds to add. So if you are trying to add more than2147483647
seconds you'll get an arithmetic overflow error. To resolve this issue you can break the addition into two calls to DateAdd one for the years and one for the remaining seconds.This will let you convert a timestamp that represents a year greater than 2038.
如果有人遇到以下错误:
因为 unix 时间戳是 bigint (而不是 int),您可以使用以下方法:
将实际列的硬编码时间戳替换为 unix-timestamp
源:MSSQL bigint Unix 时间戳到日期时间(以毫秒为单位)
If anyone getting below error:
due to unix timestamp is in bigint (instead of int), you can use this:
Replace the hardcoded timestamp for your actual column with unix-timestamp
Source: MSSQL bigint Unix Timestamp to Datetime with milliseconds
尝试:
try:
像这样
将 Unix(纪元)日期时间添加到以秒为单位的基准日期,
现在就可以得到它(2010-05-25 07:56:23.000)
如果你想反向,看看这个 http://wiki.lessthandot.com/index.php/Epoch_Date
Like this
add the Unix (epoch) datetime to the base date in seconds
this will get it for now (2010-05-25 07:56:23.000)
If you want to go reverse, take a look at this http://wiki.lessthandot.com/index.php/Epoch_Date
测试一下:
Sql 服务器:
MySql 服务器:
http://www.w3resource.com/mysql/date-and-time-functions/mysql-from_unixtime-function.php
Test this:
Sql server:
MySql server:
http://www.w3resource.com/mysql/date-and-time-functions/mysql-from_unixtime-function.php
这将做到这一点:
而不是!精度!根据时间戳的精度使用:ss、ms 或 mcs。
Bigint 能够保持微秒精度。
This will do it:
Instead of !precision! use: ss,ms or mcs according to the precision of the timestamp.
Bigint is capable to hold microsecond precision.
在
1970-01-01
中添加n
秒将为您提供 UTC 日期,因为n
– Unix 时间戳 –是自 1970 年 1 月 1 日星期四 00:00:00 协调世界时 (UTC) 以来经过的秒数。在 SQL Server 2016 中,您可以使用
时区
。您需要以 Windows 标准格式指定时区名称:或者简单地说:
注意:
DATETIMEOFFSET
转换为DATETIME
来截取时区信息。Adding
n
seconds to1970-01-01
will give you a UTC date becausen
– the Unix timestamp – is the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970.In SQL Server 2016, you can convert one time zone to another using
AT TIME ZONE
. You need to specify the name of the time zone in Windows standard format:Or simply:
Notes:
DATETIMEOFFSET
toDATETIME
.如果时间以毫秒为单位并且需要保存它们:
If the time is in milliseconds and one need to preserve them:
我也不得不面对这个问题。不幸的是,没有一个答案(这里和其他几十页)令我满意,因为由于某处的 32 位整数转换,我仍然无法达到 2038 年之后的日期。
最终对我有用的解决方案是使用
float
变量,因此我的最大日期至少为2262-04-11T23:47:16.854775849
。尽管如此,这并没有涵盖整个datetime
域,但它足以满足我的需求,并且可能会帮助遇到相同问题的其他人。有一些要点需要考虑:
@ticksofday
和算法的第一行。1900-01-01
是datetime2
的原始日期,就像 UNIX 时间戳的纪元1970-01-01
一样。datetime
。不幸的是,不允许从数值到datetime2
的显式转换,但允许显式地将数字转换为datetime
,而这又会隐式转换为>日期时间2
。目前这可能是正确的,但在 SQL Server 的未来版本中可能会发生变化:要么有一个dateadd_big()
函数,要么允许显式转换为datetime2
或者显式转换为datetime
将被禁止,因此这可能会中断,或者有一天可能会出现更简单的方法。I had to face this problem, too. Unfortunately, none of the answers (here and in dozens of other pages) has been satisfactory to me, as I still cannot reach dates beyond the year 2038 due to 32 bit integer casts somewhere.
A solution that did work for me in the end was to use
float
variables, so I could have at least a max date of2262-04-11T23:47:16.854775849
. Still, this doesn't cover the entiredatetime
domain, but it is sufficient for my needs and may help others encountering the same problem.There are some points to consider:
@ticksofday
and the first line of the algorithm accordingly.1900-01-01
is the origin date fordatetime2
, just as is the epoch1970-01-01
for unix timestamps.float
s helped me to solve the year-2038-problem and integer overflows and such, but keep in mind that floating point numbers are not very performant and may slow down processing of a big amount of timestamps. Also, floats may lead to loss of precision due to roundoff errors, as you can see in the comparison of the example results for the max date above (here, the error is about 1.4425ms).datetime
. Unfortunately, there is no explicit cast from numeric values todatetime2
allowed, but it is allowed to cast numerics todatetime
explicitly and this, in turn, is cast implicitly todatetime2
. This may be correct, for now, but may change in future versions of SQL Server: Either there will be adateadd_big()
function or the explicit cast todatetime2
will be allowed or the explicit cast todatetime
will be disallowed, so this may either break or there may come an easier way some day.@DanielLittle 对具体问题有最简单、最优雅的答案。但是,如果您有兴趣转换为特定时区并考虑 DST(夏令时),则以下方法效果很好:
注意:此解决方案仅适用于 SQL Server 2016 及更高版本(和 Azure)。
要创建函数:
您可以像这样调用该函数:
@DanielLittle has the easiest and most elegant answer to the specific question. However, if you are interested in converting to a specific timezone AND taking into account DST (Daylight Savings Time), the following works well:
Note: This solution only works on SQL Server 2016 and above (and Azure).
To create a function:
You can call the function like so:
这是基于 Daniel Little 对此问题所做的工作,但考虑到夏令时(由于 dateadd 函数的 int 限制,适用于日期 01-01 以及更大的日期):
我们首先需要创建一个表来存储夏令时的日期范围(来源:美国时间的历史):
现在我们为每个美国时区创建一个函数。这是假设 unix 时间以毫秒为单位。如果以秒为单位,请从代码中删除 /1000:
Pacific
Eastern
Central
Mountain
Hawaii
亚利桑那
阿拉斯加
This is building off the work Daniel Little did for this question, but taking into account daylight savings time (works for dates 01-01 1902 and greater due to int limit on dateadd function):
We first need to create a table that will store the date ranges for daylight savings time (source: History of time in the United States):
Now we create a function for each American timezone. This is assuming the unix time is in milliseconds. If it is in seconds, remove the /1000 from the code:
Pacific
Eastern
Central
Mountain
Hawaii
Arizona
Alaska
对于 GMT,这是最简单的方法:
For GMT, here is the easiest way:
更好的?该函数将以毫秒为单位的 unixtime 转换为 datetime。它损失了几毫秒,但对于过滤仍然非常有用。
Better? This function converts unixtime in milliseconds to datetime. It's lost milliseconds, but still very useful for filtering.
解决方案可以如下:
Solution can be the following:
这是我使用的函数,它通过执行两步
dateadd()
来处理大于 2038 的日期。它返回 UTC,但请参阅例如 Kenny 的回答了解时区和 DST 处理。Here's the function I use, which works for dates larger than 2038 by doing a two-step
dateadd()
. It returns UTC, but see e.g. Kenny's answer for timezone and DST handling.在 SQL Server 上你可以尝试这个:
SELECT
dateadd(S, CAST(CONVERT(INT, CONVERT(VARBINARY, SUBSTRing('Timestamp', 1, 8), 2)) AS NUMERIC(20)), '1970-01-01')
示例:
SELECT
dateadd(S, CAST(CONVERT(INT, CONVERT(VARBINARY, SUBSTRING('6369841c05df306d5dc81914', 1, 8), 2)) AS NUMERIC(20)), '1970-01-01')
On SQL server you can try this:
SELECT
dateadd(S, CAST(CONVERT(INT, CONVERT(VARBINARY, SUBSTRing('Timestramp', 1, 8), 2)) AS NUMERIC(20)), '1970-01-01')
Example:
SELECT
dateadd(S, CAST(CONVERT(INT, CONVERT(VARBINARY, SUBSTRING('6369841c05df306d5dc81914', 1, 8), 2)) AS NUMERIC(20)), '1970-01-01')
@salman,@daniel-little
我认为丹尼尔的答案是错误的。
他的逻辑仅使用闰年的秒数进行计算。所以转换后的值不正确。
我认为我们需要如下函数:
我使用组件验证了边缘情况,如下所示:
我的函数返回的值全部匹配源日期时间,但是,丹尼尔的逻辑返回的值并不全部匹配源日期时间。
@salman , @daniel-little
I think that Daniel's answer is wrong.
His logic calculates using only seconds of leap year. So converted values are not correct.
I think that we need the function as follows:
I verified edge cases using components as follows:
Returned values by my function all match source datetime, however, Retruned values by Daniel's logic do not all match source datetime.
结合
sys.time_zone_info
,您可以检查您的本地时区。In combination with
sys.time_zone_info
, you can check your local timezone.