DateTime.ParseExact 到 NodaTime ZonedDateTime 问题

DateTime.ParseExact to NodaTime ZonedDateTime issue

我在将解析的 string 转换为正确的 NodaTime ZonedDateTime 时遇到问题。下面的方法接受一个由代理服务器推送的字符串(据称是 UTC),并且 returns 一个 ZonedDateTime 并且 DateTimeZone 被设置为 UTC。域模型将只接受 ZonedDateTime 个对象,所以这是在系统边界发生的。

例如,作为参数传递的 string 恰好是 '2017060623:20:10' 那么 return 就会像 2017-06-06T13-:20 这样的 ZonedDateTime :10(奇怪的是十小时时差,我在悉尼的本地时区是 +10 UTC)。

public static ZonedDateTime GetZonedDateTimeUtcFromMarketDataString(string dateTime)
{
    var dotNetDateTime = DateTime.ParseExact(
        dateTime,
        "yyyyMMddHH:mm:ss,                
        CultureInfo.InvariantCulture)
        .ToUniversalTime();

    return new ZonedDateTime(Instant.FromDateTimeUtc(dotNetDateTime), DateTimeZone.Utc);
}

所以我将方法更改为下面的方法,这很有效,但我相信还有更好的方法。我确定我的错误是我以某种方式涉及我的本地时区,而不是将所有内容都保留在 UTC 中。

public static ZonedDateTime GetZonedDateTimeUtcFromMarketDataString(string dateTime)
{
    var parsedDateTime = DateTime.ParseExact(
        dateTime,
        "yyyyMMddHH:mm:ss",
        CultureInfo.InvariantCulture);

    var dotNetDateTime = new DateTime(
        parsedDateTime.Year,
        parsedDateTime.Month,
        parsedDateTime.Day,
        parsedDateTime.Hour,
        parsedDateTime.Minute,
        parsedDateTime.Second,
        DateTimeKind.Utc);

    return new ZonedDateTime(Instant.FromDateTimeUtc(dotNetDateTime), DateTimeZone.Utc);
}

DateTime.ParseExact函数可以将DateTimeStyle作为参数。

试试这个

var parsedDateTime = DateTime.ParseExact(
    dateTime,
    "yyyyMMddHH:mm:ss",
    CultureInfo.InvariantCulture, 
    DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);

我建议根本不要使用 DateTime。您正在使用 Noda Time - 所以全力以赴:)

要将文本解析为 ZonedDateTime,您可以使用 ZonedDateTimePattern。这是一个例子:

using System;
using NodaTime;
using NodaTime.Text;

class Program
{
    static void Main(string[] args)
    {
        string text = "2017060623:20:10";
        Console.WriteLine(GetZonedDateTimeUtcFromMarketDataString(text));

    }

    static readonly ZonedDateTimePattern ParsePattern =
        ZonedDateTimePattern.CreateWithInvariantCulture(
           "yyyyMMddHH:mm:ss",
           DateTimeZoneProviders.Tzdb); // Won't actually be used...

    static ZonedDateTime GetZonedDateTimeUtcFromMarketDataString(string dateTime)
        => ParsePattern.Parse(dateTime).Value;
}

默认模板值已经使用 UTC 作为时区,因此您无需担心。

或者,您可以使用 LocalDateTimePattern,因为您使用的文本未指定时区 - 解析为 LocalDateTime,然后调用 LocalDateTime.InUtc()

所有这些都提出了另一个问题,这就是为什么您要将值解析为 ZonedDateTime 的原因。如果您 总是 有一个 UTC 值,您真的需要它是 ZonedDateTime 而不是 Instant 吗?您不知道最初观察到该值的时区,所以对我来说更像是一个时间点。