在 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 时间戳?的主要内容,如果未能解决你的问题,请参考以下文章

sqlserver中将datetime类型转换为yyyyMMddHHmmss格式

在雅典娜中将具有时区偏移的字符串转换为日期时间

mysql中将datetime转换为int格式

如何在sybase中将字符串转换为日期

在 SQL Server 中将字符串转换为日期

在 pandas.Series 中将时间戳转换为 datetime.datetime