将字符串转换为指定时区(非本地或 UTC)中的 DateTime

Convert string to DateTime in a specified TimeZone (not local nor UTC)

提问人:Milana 提问时间:8/13/2023 最后编辑:Milana 更新时间:8/21/2023 访问量:126

问:

我表示为字符串(例如“2023-08-13T11:32:59”) 但此时区不是 UTC 也不是本地时区DateTimeDateTime

我想解析此字符串,然后将其转换为本地时区。

到目前为止,我所做的是将其转换为UTC,然后转换为本地时区。 我写了这个代码可以完成这项工作,但看起来很麻烦,有没有更好的方法?

DateTime sourceDateTime = DateTime.Parse(date);
TimeZoneInfo sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");

DateTime unspecified = DateTime.SpecifyKind(sourceDateTime, DateTimeKind.Unspecified);
DateTime utcDateTime = TimeZoneInfo.ConvertTimeToUtc(unspecified, sourceTimeZone);

DateTime result = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, TimeZoneInfo.Local);
C# .NET 日期时间 时区

评论

0赞 Zohar Peled 8/13/2023
让我看看我是否理解:您有在特定时区(中欧标准时间)中指定的日期时间的字符串表示形式,并且您想从中提取本地日期时间值?这是对的吗?
0赞 Charlieface 8/13/2023
你知道 TZ 的名称或实际偏移量吗?您是否需要考虑夏令时,如果是,如何考虑?
0赞 Milana 8/14/2023
@ZoharPeled是的
0赞 Milana 8/14/2023
@Charlieface是的,给出了 TZ,在上面的示例中它是“中欧标准时间”。我所做的是首先转换为UTC,然后转换为我本地的TZ

答:

0赞 jdweng 8/14/2023 #1

尝试:

            string strDate = "2023-08-13T11:32:59";
            DateTime utcTime = DateTime.Parse(strDate, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeUniversal);
            System.TimeZoneInfo sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");

            DateTime date = System.TimeZoneInfo.ConvertTime(utcTime, sourceTimeZone);

评论

0赞 Milana 8/15/2023
在这里,您假设给定的日期是 UTC,但我询问了第三时区的给定日期。不是 UTC 或本地
0赞 jdweng 8/15/2023
然后你需要两个时区,比如 Zohar 解决方案。
1赞 Zohar Peled 8/14/2023 #2

该类有一个静态方法,用于将值从一个时区转换为另一个时区 - 称为 ConvertTime - 您所要做的就是获取该类的两个实例,一个用于源,一个用于目标,并使用该方法:TimeZoneInfoDateTimeTimeZoneInfo

var datetimeString = "2023-08-13T11:32:59";
var sourceTimeZoneId = "Central European Standard Time"; // UTC + 1
var targetTimeZoneId = "Israel Standard Time"; // UTC + 2 

var sourceDatetime = DateTime.Parse(datetimeString);
// sourceDateTime.Kind property is already Unspecified, no need to change that

var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(sourceTimeZoneId);
var targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById(targetTimeZoneId);

var targetDateTime = TimeZoneInfo.ConvertTime(sourceDatetime, sourceTimeZone, targetTimeZone);

// targetDateTime is 2023-13-08T12:32:59, kind is still unspecified.

您可以在 SharpLab.IO 上观看现场演示

1赞 Matt Johnson-Pint 8/15/2023 #3

有几件事:

  • 解析后您已经有 kind,因此无需再次指定。sourceDateTimeUnspecified

  • 您无需通过 UTC - 您可以使用该方法直接从源时区转换为目标时区。TimeZoneInfo.ConvertTime

因此,简化版本为:

DateTime sourceDateTime = DateTime.Parse("2023-08-13T11:32:59");
TimeZoneInfo sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");

DateTime result = TimeZoneInfo.ConvertTime(sourceDateTime, sourceTimeZone, TimeZoneInfo.Local);

请确保您还了解如何处理 DST 转换附近可能出现的不明确和无效值。从文档中ConvertTimeDateTime

如果参数的值是源时区中的不明确时间,则将其解释为标准时间。如果参数是源时区的无效时间,则此方法将引发 .dateTimedateTimeArgumentException

如果这不是您想要的行为,则可能需要实现其他逻辑。

评论

0赞 Milana 8/15/2023
我知道我缺少一些内置方法。感谢您的详细解释!