C#使用特定的TimeZone将字符串解析为DateTime

时间:2019-07-01 17:30:33

标签: c# datetime timezone

我一直在为此苦苦挣扎,所以我会坚持下去。

我有一个应用程序,需要在其中将字符串解析为日期时间。字符串如下所示:

"201503131557"

(它们始终为“ yyyyMMddHHmm”格式),即使未指定,也始终处于“中央标准时间”(或中央夏令时,具体取决于日期)。

当我解析它们时,我了解它会将它们解析为本地时间。我在Azure PaaS上运行,并且不想为了支持此操作而将其更改为在CST中运行。

我如何编写可在本地和Azure PaaS中使用的代码,以将这些日期正确解析为DateTimes并将其时区设置为CST?

这是我为证明马特·约翰逊的答案而编写的快速单元测试。

    [TestMethod]
    public void DateTests()
    {
        var unSpecDt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);
        var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");


        var utcDt = TimeZoneInfo.ConvertTimeToUtc(unSpecDt, tz);

        var offset = tz.GetUtcOffset(unSpecDt);
        var dto =new DateTimeOffset(unSpecDt, offset);


        var cstDt = dto.DateTime;

        Assert.IsTrue(cstDt.Hour - utcDt.Hour == offset.Hours);
    }

3 个答案:

答案 0 :(得分:3)

要解析字符串,因为您只有日期和时间,并且知道字符串将采用的特定格式,请执行以下操作:

DateTime dt = DateTime.ParseExact("201503131557", "yyyyMMddHHmm", CultureInfo.InvariantCulture);

结果值会将其Kind属性设置为DateTimeKind.Unspecified(不是您所想的本地时间)。这是意料之中的,因为您未提供有关此时间戳记与UTC或本地时间之间的关系的信息。

您说的值代表中央标准时间的时间。您将需要一个了解该时区的TimeZoneInfo对象。

TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");

请注意,此标识符表示在美国观察到的中部时间,包括CST或CDT,这取决于给定值的生效时间(尽管名称中带有“标准”字样)。还要注意,它仅在Windows操作系统上有效。如果要在其他操作系统上使用.NET Core,则需要传递IANA标识符"America/Chicago"(或使用我的TimeZoneConverter库在任何平台上使用任一标识符)。

下一步是找出要使用此值进行 的操作。您可能会用它做一些不同的事情:

  • 如果要将其转换为等效的UTC值(表示为DateTime),则可以执行以下操作:

    DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
    
  • 如果您想要一个DateTimeOffset表示形式来保存您提供的输入以及与美国中部时间相关的UTC偏移量,则可以执行以下操作:

    TimeSpan offset = tz.GetUtcOffset(dt);
    DateTimeOffset dto = new DateTimeOffset(dt, offset);
    

    请记住,如果输入时间接近DST转换,则输入时间可能无效或含糊。在这种情况下,GetUtcOffset方法将返回 standard 偏移量。如果您想要不同的行为,则可以编写更多代码(超出本文范围)。

  • 您还可以做其他事情,所有这些工作都由TimeZoneInfo类提供。

请注意,“ Azure PaaS”可能指的是一些不同的东西,尽管Azure App Service中有一个名为WEBSITE_TIME_ZONE的设置-我不建议您依靠它。认为只有在无法控制代码时才可以使用它。在大多数情况下,最好不要编写代码来完全不依赖于运行它的系统的时区设置。这意味着永远不要调用DateTime.NowTimeZoneInfo.LocalDateTime.ToLocalTime甚至DateTime.ToUniversalTime(因为它会转换 from 本地时区),等等。而是依赖与UTC或特定时区或偏移量显式兼容的方法。这样一来,您就不必担心应用程序的托管位置。

最后,请了解DateTimeDateTimeOffset类型都不具有将值绑定到特定时区的能力。为此,您需要编写自己的类,或者查看其ZonedDateTime类提供此类功能的Noda Time库。

答案 1 :(得分:0)

您可以使用:

DateTime.ParseExact(...)


public static DateTime ParseExact (string s, string format, IFormatProvider provider);

此日期时间没有有关时区的任何元数据。您可以转换为UTC,然后确保可以转换为所有时区。

答案 2 :(得分:0)

DateTime.TryParseExact(...)方法与DateTimeStyles.RoundtripKind一起使用以避免转换。

DateTime dt;
DateTime.TryParseExact("201503131557", "yyyyMMddHHmm", null, System.Globalization.DateTimeStyles.RoundtripKind, out dt);

如果需要进行转换,则需要转到UTC,然后将TimeZoneInfoTimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")一起使用转换方法。