在 Select 语句中将 DateTime 转换为 Unix 时间戳?
Posted
技术标签:
【中文标题】在 Select 语句中将 DateTime 转换为 Unix 时间戳?【英文标题】:Cast DateTime to Unix Timestamp in Select statement? 【发布时间】:2015-04-13 06:38:44 【问题描述】:我确实有一个数据库表,其中包含数百万个存档值行,其中包含一个值(单个)、两个整数 id 字段和一个日期时间字段(以及与我要构建的缓存无关的一些其他字段) .表结构是固定的,我无法更改。现在我想将所有行读入一个简单类的对象数组中,我想将其保存在内存中以进行缓存。
为了保持低内存消耗,我想使用 unix 时间戳而不是 datetime 对象。这也很有用,因为将连续使用此缓存的前端图表等也可以原生使用 Unix 时间戳。
对于缓存创建,我想select 直接进入一个ArchiveElement。这适用于大多数领域,但我不知道如何在 select 语句中动态创建 Unix 时间戳:
ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement()
DataPointId = (UInt16)x.DataPointId,
StationId = (UInt16)x.StationId,
Value = (Single)x.Value,
DateValue = x.DateValue // <-- Here I want to cast into Unix Timestamp
);
这是 ArchiveElement 类:
public class ArchiveElement
public UInt32 DateValue;
public UInt16 DataPointId;
public UInt16 StationId;
public Single Value;
我的应用程序中有一个函数可以将 DateTime
转换为 Unix 时间戳,但这在 select
语句的范围内不起作用。所以我需要另辟蹊径。
一种方法是在.Select(..)
语句之前插入.ToList()
,这样我就可以访问我自己的函数,但这将是一个丑陋的解决方法,因为它会从数据库中获取很多不必要的字段。
有没有办法以某种方式“就地”转换日期时间?
【问题讨论】:
它会获取很多不必要的字段吗?看起来你无论如何都想拉整张桌子 DB 表还有一些字段我这里没有提到,只是为了简单起见。 Unix 时间戳到底是什么意思?您是指纪元时间,例如 1423748783? 我的意思是自 1970 年 1 月 1 日以来的秒数。(所有时间都是 UTC,转换为本地时间会在前端稍后发生)。 【参考方案1】:所以首先你声明 Unix 纪元时间:
var unixEpoch = DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
现在在您的Select
中,只需从您的日期值中减去纪元即可得到TimeSpan
类型,您可以从中获得TotalSeconds
,这是您需要的值:
ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement()
DataPointId = (UInt16)x.DataPointId,
StationId = (UInt16)x.StationId,
Value = (Single)x.Value,
DateValue = (x.DateValue - unixEpoch).TotalSeconds
);
注意:这假设您的 DateValue
属性是双精度的,您可能需要将其转换为 long
。
编辑
为了应对实体框架,这可能有效:
ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement()
DataPointId = (UInt16)x.DataPointId,
StationId = (UInt16)x.StationId,
Value = (Single)x.Value,
DateValue = SqlFunctions.DateDiff("ss", unixEpoch, x.DateValue)
);
这可能需要System.Data.Entity.SqlServer
的引用/导入。
【讨论】:
这会引发 System.ArgumentException (DbArithmeticExpression)。 啊,我忘了这是实体框架。你可以在Select
之前做ToList()
?
如果我这样做了,我也可以使用我自己的函数;-)【参考方案2】:
DATEDIFF(SECOND,d '1970-01-01', GETUTCDATE())
这将返回 sql 中的 unix 秒数。
【讨论】:
以上是关于在 Select 语句中将 DateTime 转换为 Unix 时间戳?的主要内容,如果未能解决你的问题,请参考以下文章