我在CSV文件中有一个日期,它是SSIS脚本任务的字符串。
我需要根据字符串中存在的GMT偏移量将日期转换为本地时间-我想将其转换为datetime
并将其保存在数据库中。
我得到的日期时间是
2018-06-21 08:55 GMT-0400
我需要将其存储为
2018-06-21 08:55
假设我的当地时间是美国东部时间。
为此,我使用以下代码:
DateTime dt; // datetime variable
string str; // string variable
string format = "yyyy-MM-dd HH:mm:ss";
str = Row.Dateused;
if (Row.Dateused_IsNull == false)
{
// convert datetime format to standard one
DateTime.TryParseExact(str, format, CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal |DateTimeStyles.AdjustToUniversal,out dt);
Row.Dateused = dt.ToString();
}
但是当我执行它时,这就是我得到的输出:
1/1/0001 12:00:00
有人可以告诉我我要去哪里错吗?
答案 0 :(得分:0)
简短版本
ParseExact的正确模式是"yyyy-MM-dd HH:mm 'GMT'zzzzz"
。最好使用的类型是DateTimeOffset
。
如果使用DateTime
,则它应具有DateTimeStyles.AdjustToUniversal
才能获得UTC时间。
在任何情况下,都应将强类型值而不是字符串传递给数据库,以避免转换错误。
长版
处理时区时,正确的类型是DateTimeOffset
,而不是DateTime
。 DateTime无法理解时区,因此它假定时间是UTC或运行此代码的计算机的 local 时区。它不了解local
的实际含义。
DateTime和DateTimeOffset都可以使用正确的模式来解析此字符串:
"yyyy-MM-dd HH:mm 'GMT'zzzzz"
例如:
var pattern="yyyy-MM-dd HH:mm 'GMT'zzzzz";
var dt=DateTimeOffset.ParseExact("2018-06-21 08:55 GMT-0400",pattern,CultureInfo.InvariantCulture);
Console.WriteLine("{0:O}",dt);
将打印:
2018-06-21T08:55:00.0000000-04:00
DateTime属性可以使用DateTimeKind.Unspecified返回不带偏移量的日期和时间。以下代码:
DateTime dtOnly=dt.DateTime;
Console.WriteLine("{0:O}",dtOnly);
将打印:
2018-06-21T08:55:00.0000000
在数据库中使用datetimeoffset
还是更好,并避免例如由于夏令时转换而引起的错误。如果类型必须为datetime
(为什么?),则应首先使用UtcDateTime将其转换为UTC。但是,这将丢失偏移信息。
Console.WriteLine("{0:O}",dt.UtcDateTime);
将打印:
2018-06-21T12:55:00.0000000Z
使用DateTimeKind.Utc
DateTime怎么样?
DateTime.ParseExact
也可以使用,但是结果取决于 local 时区。这是因为ParseExact将看到偏移量,并返回调整为 local 时区(无论是什么时间)或UTC的DateTime。返回08:55
的唯一方法是,如果这是当前计算机的时区偏移量。
在我的机器上,偏移量是+3:00。所以
DateTime.ParseExact("2018-06-21 08:55 GMT-0400",pattern,CultureInfo.InvariantCulture,DateTimeStyles.AssumeLocal);
将使用种类=本地返回2018-06-21T15:55:00
。与AssumeUniversal
相同,因为字符串不是UTC,它具有偏移量。
DateTimeStyles.AdjustToUniversal
将导致2018-06-21T12:55:00
带有Kind Utc。可以正确地将相应的UTC值存储在数据库中,而不会引起太多混乱,