在 Select 语句中将 DateTime 转换为 Unix 时间戳?
Cast DateTime to Unix Timestamp in Select statement?
我确实有一个数据库 table,其中包含数百万个存档值行,这些行由一个值(单个)、两个整数 ID 字段和一个日期时间字段(以及一些与我要构建的缓存)。 table 结构是固定的,我不能改变它。现在我想将所有行读入一个简单的 class 对象数组,我想将其保留在内存中以用于缓存目的。
为了保持低内存消耗,我想使用 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 class:
public class ArchiveElement
{
public UInt32 DateValue;
public UInt16 DataPointId;
public UInt16 StationId;
public Single Value;
}
我的应用程序中确实有一个函数可以将 DateTime
转换为 Unix 时间戳,但它在 select
语句的范围内不起作用。所以我需要另辟蹊径。
一种方法是在 .Select(..)
语句之前插入一个 .ToList()
,这样我就可以访问我自己的函数,但这将是一个丑陋的解决方法,因为它会获取很多不必要的来自数据库的字段。
有没有办法以某种方式转换日期时间"in place"?
所以首先声明 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
。
编辑
为了应对 Entity Framework,这可能有效:
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)
});
这可能需要 reference/import for System.Data.Entity.SqlServer
。
DATEDIFF(SECOND,{d '1970-01-01'}, GETUTCDATE())
这将 return sql 的 unix 秒数。
我确实有一个数据库 table,其中包含数百万个存档值行,这些行由一个值(单个)、两个整数 ID 字段和一个日期时间字段(以及一些与我要构建的缓存)。 table 结构是固定的,我不能改变它。现在我想将所有行读入一个简单的 class 对象数组,我想将其保留在内存中以用于缓存目的。
为了保持低内存消耗,我想使用 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 class:
public class ArchiveElement
{
public UInt32 DateValue;
public UInt16 DataPointId;
public UInt16 StationId;
public Single Value;
}
我的应用程序中确实有一个函数可以将 DateTime
转换为 Unix 时间戳,但它在 select
语句的范围内不起作用。所以我需要另辟蹊径。
一种方法是在 .Select(..)
语句之前插入一个 .ToList()
,这样我就可以访问我自己的函数,但这将是一个丑陋的解决方法,因为它会获取很多不必要的来自数据库的字段。
有没有办法以某种方式转换日期时间"in place"?
所以首先声明 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
。
编辑
为了应对 Entity Framework,这可能有效:
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)
});
这可能需要 reference/import for System.Data.Entity.SqlServer
。
DATEDIFF(SECOND,{d '1970-01-01'}, GETUTCDATE())
这将 return sql 的 unix 秒数。