在填充的数据表中将 datetime 列从 utc 转换为本地时间

Posted

技术标签:

【中文标题】在填充的数据表中将 datetime 列从 utc 转换为本地时间【英文标题】:Convert datetime column from utc to local time in a populated datatable 【发布时间】:2020-01-20 16:28:10 【问题描述】:

我正在尝试使用 EPPLUS 将一些数据从 Sql Server 导出到一个 excel 文件中,并传递一个自定义 sql select statemet。这工作正常,但问题是日期时间字段以 UTC 格式存储在数据库中,而不是我想以本地时区格式(es.GMT +2)显示它们。有没有办法以最小的性能损失来完成?使用 EPPLUS 方法在数据表或 excel 文件中转换列都没有关系。我希望最终输出以 +2 小时为单位显示时间。

我尝试添加 DataColumn col.ExtendedProperties.Add("TZ", +2);但没有任何改变。 DataColumn.DateTimeMode 不适用于填充的 DataTable。我正在尝试用添加 +2 小时的公式替换 excel 列,但我无法弄清楚。 下面你可以看到我的代码。

string connString = @"Data Source=" + DataSourceName + ";Initial Catalog=" + InitialCatalog + ";User ID=" + UserID + "; Password=" + password + ";Integrated Security=SSPI;";
            SqlConnection conn = new SqlConnection(connString);
            conn.Open();
            //retreive data from the report query
            SqlCommand Reportcmd = new SqlCommand(ReportQuery, conn);
            Reportcmd.CommandTimeout = 0;
            SqlDataAdapter Reportda = new SqlDataAdapter(Reportcmd);
            Reportda.Fill(ReportDtTbl);
            conn.Close();
            //var fileName = "Example-CRM-" + DateTime.Now.ToString("yyyy-MM-dd--hh-mm-ss") + ".xlsx";

            MemoryStream stream = new MemoryStream();
            using (ExcelPackage pck = new ExcelPackage(stream))
            
                ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Report");
                Tempaltesheet.Cells[1, 1, 1, 100].Copy(ws.Cells[1, 1, 1, 100]);  //Cells[RowStart, ColumnStart, RowEnd, ColumnEnd ]
                int colNumber = 1;

                foreach (DataColumn col in ReportDtTbl.Columns)
                
                    if (col.DataType == typeof(DateTime))
                    
                        ws.Column(colNumber).Style.Numberformat.Format = "dd/MM/yyyy hh:mm:ss";
                        //DataColumn col.ExtendedProperties.Add("TZ", +2);
                    
                    colNumber++;
                
                ws.Cells["A2"].LoadFromDataTable(ReportDtTbl, false);
                // save our new workbook in the output directory and we are done!
                ReportExcel = pck.GetAsByteArray();
                //pck.Save();
            
            return ReportExcel;

【问题讨论】:

如果日期存储在 DateTime 中,则无需转换。只要确保您在当地时间显示。如果日期存储不正确,则需要进行更改。如果您确实需要进行更改,最好的方法是使用 SQL Server Management Studio 并编写一个 SQL 过程。 【参考方案1】:

您应该更改对数据库的查询以考虑与 UTC 相比的本地时间差异,而不是在返回数据后更改日期时间。

SELECT CONVERT(datetime, 
           SWITCHOFFSET(CONVERT(datetimeoffset, 
                                MyTable.UtcColumn), 
                        DATENAME(TzOffset, SYSDATETIMEOFFSET()))) 
   AS ColumnInLocalTime
FROM MyTable

如本答案所述,不要减去小时数: Convert Datetime column from UTC to local time in select statement

【讨论】:

A familiar-looking answer 还指出,这不会针对 DST 进行调整。【参考方案2】:

因为它已经是日期时间类型:

 TimeZoneInfo tz= TimeZoneInfo.FindSystemTimeZoneById("<timezone column?>");//"Central Standard Time"
   DateTime tzTime = TimeZoneInfo.ConvertTimeFromUtc(<utctime>, tzTime );

使用 IsDaylightSavingTime 检查夏令时。

如果您不知道本地时区是什么(它不存储在一个 coumn 中),请使用 ToLocalTime 作为当前时区。

【讨论】:

以上是关于在填充的数据表中将 datetime 列从 utc 转换为本地时间的主要内容,如果未能解决你的问题,请参考以下文章

在python中将日期时间从PDT转换为UTC

在python中将列从一个数据帧添加到分组数据帧

在 Synapse 中将时间戳从字符串转换为 EST 时间

在scala中将列从一个数据帧添加到另一个数据帧[重复]

使用数据工厂根据 Datetimestamp 列从存储帐户中选择文件

如何在一系列行中将 1 列从一个数据库复制到另一个数据库