SQL Server / OLEDB DateTimes到NodaTime即时 - 最安全的方法

时间:2015-01-19 11:17:33

标签: datetime timezone oledb nodatime

当原始数据来自SQL查询(本例中为LINQ)或OLEDB(两者都相同)时,我遇到转换日期时间的问题。

我正在使用NodaTime,但问题是我似乎需要在进入Noda Instant之前通过System.DateTime,此时会引入错误。

源数据中的数据时区始终是已知的,在大多数情况下是UTC。但是由于某些原因,代码将其解释为本地系统时间(我猜),就像当我调用ToUniversalTime()时,它将时间戳移动了一个小时。

将数据库日期时间对象转换为NodaTime Instant的最佳方法是什么,而不存在任何系统时间干预的风险?

我知道源数据的时区,我需要将其转换为正确的Instant,而系统不会在后台应用假定的TimeZone。

示例OleDb代码:

var cmd = String.Format("SELECT [{0}] AS EquipRef, [{1}] AS MeasureTimeStamp, [{2}] AS MeasureValue FROM [{3}]", equipRefColumn, timeStampColumn, columnName, tableName);
var dataTable = new DataTable(tableName);

using (var adapter = new OleDbDataAdapter(cmd, conn)) {
    adapter.Fill(dataTable);
}

var dataContainer = new DataContainer();
dataContainer.Data.Add(tableName, new List<Row>());

foreach (DataRow row in dataTable.Rows) {
    var timeStamp = Instant.FromDateTimeUtc(((DateTime)row["MeasureTimeStamp"]).ToUniversalTime());
    dataContainer.Data[tableName].Add(new Row() {ColumnName = columnName,EquipRef = row["EquipRef"].ToString(), TimeStamp = timeStamp, Value = row["MeasureValue"]});
}

示例LINQ to SQL代码:

var db = new RawDataStoreDataContext(new SqlConnection(ConnectionString));

var tables = db.Tables_Get(SourceDataLinkId);
var equipRefs = db.EquipRefs_Get(SourceDataLinkId);

foreach (var table in tables) {
    foreach (var equipRef in equipRefs) {
        var rawData = db.RawData_FetchByTableAndEquip(equipRef.EquipRef, table.TableName, SourceDataLinkId);

        var dataContainer = new DataContainer();
        dataContainer.Data = new Dictionary<string, List<Row>>();

        dataContainer.Data.Add(table.TableName,new List<Row>());
        foreach (var row in rawData) {
            var timeStamp = Instant.FromDateTimeUtc(row.TimeStamp.ToUniversalTime());
            dataContainer.Data[table.TableName].Add(new Row() {ColumnName = row.ColumnName,EquipRef = equipRef.EquipRef,TimeStamp = timeStamp,Value = row.Value});
        }
        dataTarget.Stage(dataContainer);
    }
}

1 个答案:

答案 0 :(得分:2)

而不是ToUniversalTime,请使用DateTime.SpecifyKind并传递DateTimeKind.Utc

在您的OLEDB代码中:

var timeStamp = Instant.FromDateTimeUtc(DateTime.SpecifyKind((DateTime)row["MeasureTimeStamp"], DateTimeKind.Utc));

在您的L2S代码中:

var timeStamp = Instant.FromDateTimeUtc(DateTime.SpecifyKind(row.TimeStamp, DateTimeKind.Utc));