SQL Server / OLEDB DateTimes для NodaTime Instant - самый безопасный метод

У меня есть проблема с преобразованием времени даты, когда исходные данные поступают из запроса SQL (в данном случае LINQ) или через OLEDB (та же проблема для обоих).

Я использую NodaTime, однако проблема в том, что мне нужно пройти через System.DateTime, прежде чем перейти к Noda Instant, и в этот момент появляются ошибки.

Часовой пояс данных в исходных данных всегда известен, в большинстве случаев это его UTC. Однако по какой-то причине код интерпретирует его как локальное системное время (я полагаю), как когда я звоню ToUniversalTime() это сдвигает отметку времени на час.

Каков наилучший способ преобразования объекта datetime базы данных в NodaTime 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);
    }
}

1 ответ

Решение

Вместо 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));
Другие вопросы по тегам