簡體   English   中英

當 UTC 與時區偏移一起使用時,DateTime.Parse 方法中是否存在錯誤?

[英]Is there a bug in the DateTime.Parse method when UTC is used with time zone offsets?

Microsoft 文檔指出,在 DateTime 結構的其他字符串表示形式中,DateTime.Parse(string) 符合 ISO 8601 並接受用於時區偏移的協調世界時 (UTC) 格式。

當我運行以下單元測試用例時, DateTime.Parse(string) 和 DateTime.TryParse(string, out DateTime) 接受源字符串末尾的附加字符。 這似乎是一個錯誤。 當追加了多個附加字符時,該方法無法正確解析字符串。

[Theory]
[InlineData("2020-5-7T09:37:00.0000000-07:00")]
[InlineData("2020-5-7T09:37:00.0000000-07:00x")]
[InlineData("2020-5-7T09:37:00.0000000-07:00xx")]
[InlineData("2020-5-7T09:37:00.0000000Z")]
[InlineData("2020-5-7T09:37:00.0000000Zx")]
public void TestParse(string source)
{
    DateTime dt = DateTime.Parse(source);
    Assert.True(dt != null);
    bool b = DateTime.TryParse(source, out dt);
    Assert.True(b);
}

編寫此單元測試用例是為了簡化我的代碼並說明我所看到的行為(我認識到預期的失敗應該以不同的方式處理)。

測試 1 和 2 通過,而第三個測試(帶有“xx”后綴)失敗。 在我看來,第二個測試(帶有“x”后綴)應該會失敗。

如果未提供時區指示符,則測試 4 通過而測試 5 失敗。 這似乎是正確的行為。

我想知道是否有人遇到過這個問題,如果遇到過,是否普遍認為這是一個錯誤?

就個人而言,這對我來說似乎是一個錯誤......

2020-5-7T09:37:00.0000000-07:00x是一個有效的 ISO 8601 日期,末尾有一個無效的任意字符,它在沒有錯誤的情況下錯誤地解析,其中兩個任意字符似乎正確地失敗了。

似乎正在發生的事情如下

  1. ParseISO8601 ParseTimeZone獲取正確的時區信息-07:00
  2. 這使str有 1 個最后索引
  3. 然后它檢查str.Match('#')哪個前綴增加了索引(我認為這是錯誤)。
  4. 此時它假定解析在后續檢查中完成,因為索引位於字符串的末尾

比賽節選

評論我的

internal bool Match(char ch)
{
    if (++Index >= Length) // reaches the end of the string here
    {
        return false;
    }
    ...
}

上面的方法返回false ,但是它增加了索引。 這在事物的計划中似乎非常奇怪。

看起來它的設計目的是檢查 hash 的當前字符,然后是null 終止,如果還有其他任何內容,則失敗。

摘自 ParseISO8601

str.SkipWhiteSpaces();
if (str.Match('#'))  // mine... check hash ... no
{
   if (!VerifyValidPunctuation(ref str))
   {
      result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
      return false;
   }
   str.SkipWhiteSpaces();
}
if (str.Match('\0')) // mine... check null termination ... no
{
   if (!VerifyValidPunctuation(ref str))
   {
      result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
      return false;
   }
}
if (str.GetNext()) // mine... get anything else, if found fail
{
   // If this is true, there were non-white space characters remaining in the DateTime
   result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
   return false;
}

注意:這似乎發生在我測試過的每個框架中。

簡而言之,它會完全忽略日期末尾的任何任意字符,但是如果還剩下 2 個字符,它會按預期運行,因為它會遞減匹配檢查中的索引。

internal bool Match(char ch) {
    if (++Index >= len) {
        return (false);
    }
    if (Value[Index] == ch) {
        m_current = ch;
        return (true);
    }
    Index--;
    return (false);
}

更新 1

我已將此報告為 GitHub 上的運行時錯誤,可以在此處進行跟蹤

DateTime.Parse ISO 8601 允許在日期末尾使用額外的任意字符 #46477

更新 2

這已被正式標記為運行時錯誤,並且已為 .Net 6 修復

我還沒有時間構建運行時來檢查它實際在做什么,但是從評論看來,當它拉出時區時,當前索引遞增 1 太多,並且匹配錯誤地檢查了下一個字符。

有一個PR可以解決這個問題。 修復應該在未來的 .NET 版本 (6.0) 中。 感謝您報告問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM