有几件事:
-
您的格式说明符包括
Z
在最后。这由处理。Net的字符串格式设置为
字符文字
,因为它不是有效的
datetime formatting specifier
。请注意,格式化标记区分大小写。作为文本,它只是复制到输出中,就像
T
是因此,您生成的这个字符串总是会被任何解析它的东西解释为UTC,因为这是
Z
指ISO 8601标准中的。这最终是您面临的问题的根本原因。
如果您希望它反映一个模糊的本地时间(因为时区可能在您的.ics中的其他地方?),然后省略
Z
完全但是,如果打算包括时区偏移,则可以使用
K
的说明符
DateTime
价值观,或者
zzz
说明符与
DateTimeOffset
价值观-取决于您的具体需求。
-
正如其他人指出的那样,
日期时间
不知道时区,但请注意,两者都不知道
日期时间偏移量
因为它只跟踪UTC的偏移量,而不是特定的时区。例如,它可以跟踪
-07:00
,但它不能告诉你它是在山区。这就是野田佳彦时代
ZonedDateTime
类型Net本身没有任何这样的内置类型。
-
在代码中,而不是调用
TimeZoneInfo.ConvertTime
这个
.Kind
的
dateTime1
将考虑变量。如果是
DateTimeKind.Utc
,则结果将具有确定性。但如果是
DateTimeKind.Unspecified
或
DateTimeKind.Local
,则将其视为本地计算机的时区,即
服务器
你的情况是时区。
-
请注意,最好以行为相同的方式编写代码
不管
服务器时区的设置。这通常意味着避免
DateTimeKind。地方的
例如
DateTime.Now
,则,
TimeZoneInfo.Local
,以及其他。相反,使用
DateTime.UtcNow
用于获取当前
日期时间
。或者,您可以使用
DateTimeOffset.Now
或
DateTimeOffset.UtcNow
,或Noda Time的
IClock
实施。
归根结底,尽管有几种可能的解决方案,但要将当前时间生成为特定时区中的字符串,最简单的方法是:
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime utcNow = DateTime.UtcNow;
DateTime converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
string s = converted.ToString("yyyyMMddTHHmmss");
或者您可能需要:
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTimeOffset utcNow = DateTimeOffset.UtcNow;
DateTimeOffset converted = TimeZoneInfo.ConvertTime(utcNow, destinationTimeZone);
string s = converted.ToString("yyyyMMddTHHmmsszzz").Replace(":","");
请注意
:
通过
Replace
最后,这是因为在ISO 8601中
基本的
格式,偏移量应如下所示
-0500
而不是
-05:00
。遗憾的是,没有格式说明符可以直接获取。(仅ISO 8601
扩展的
格式使用冒号)。