SQL 服务器/OLEDB DateTimes 到 NodaTime Instant - 最安全的方法
SQL Server / OLEDB DateTimes to NodaTime Instant - Safest Method
当原始数据来自 SQL 查询(在本例中为 LINQ)或来自 OLEDB(两者相同的问题)时,我在转换日期时间时遇到问题。
我正在使用 NodaTime,但问题是我似乎需要先通过 System.DateTime 才能进入 Noda Instant,此时会出现错误。
源数据中数据的时区始终是已知的,在大多数情况下是 UTC。但是由于某种原因,代码将其解释为本地系统时间(我猜),因为当我调用 ToUniversalTime()
时,它会将时间戳移动一个小时。
在没有任何系统时间干预风险的情况下,将数据库日期时间对象转换为 NodaTime Instant 的最佳方法是什么?
据我了解源数据的时区,我需要将其转换为正确的 Instant,而无需系统在幕后应用假定的时区。
示例 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);
}
}
而不是 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));
当原始数据来自 SQL 查询(在本例中为 LINQ)或来自 OLEDB(两者相同的问题)时,我在转换日期时间时遇到问题。
我正在使用 NodaTime,但问题是我似乎需要先通过 System.DateTime 才能进入 Noda Instant,此时会出现错误。
源数据中数据的时区始终是已知的,在大多数情况下是 UTC。但是由于某种原因,代码将其解释为本地系统时间(我猜),因为当我调用 ToUniversalTime()
时,它会将时间戳移动一个小时。
在没有任何系统时间干预风险的情况下,将数据库日期时间对象转换为 NodaTime Instant 的最佳方法是什么?
据我了解源数据的时区,我需要将其转换为正确的 Instant,而无需系统在幕后应用假定的时区。
示例 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);
}
}
而不是 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));