DurationPattern 在没有分隔符的情况下无法解析

问题描述 投票:0回答:1

我的任务是以“HHmm”格式表示持续时间。这至少在名义上是 Nodatime.DurationPattern 解析时应该没有问题的,因为它遵循here指定的要求。事实上,它是作为可以使用的模式的示例而专门提到的。

如果不在小时和分钟之间添加某种分隔符,我就无法正确解析它(例如“HH | mm”或“HH!mm”等将解析没有问题)。

我编写了这个测试代码来演示该问题:

    public void ConvertWithPattern()
{
    var result1 = DurationPattern.CreateWithInvariantCulture("HH mm").Parse("12 13");
    var result2 = DurationPattern.CreateWithInvariantCulture("HHmm").Parse("1213");

    Assert.True(result1.Success);
    Assert.Equal(12, result1.Value.Hours);
    Assert.Equal(13, result1.Value.Minutes);
    Assert.True(result2.Success);  // this assertion fails
    Assert.Equal(result1, result2);
}

失败的 ParseResult 报告显示 UnparsableValueException 并显示以下消息:

值字符串与格式中所需的数字不匹配 字符串“毫米”。正在解析的值:'1213^'。 (^表示错误 位置。)

有什么方法可以用 Nodatime.DurationPattern 解析这个模式吗?

parsing duration nodatime
1个回答
0
投票

有什么方法可以用 Nodatime.DurationPattern 解析这个模式吗?

有潜力。作为解释,当使用“总值”说明符(如

H
)时,出现的字母数将用作 minimum 数字,而不是 maximum。它将解析尽可能多的数字(无论如何,最多 13 个)。所以基本上 Noda Time 正在解析“1213 小时”的值,然后查找分钟 - 这就是出错的地方。

如果您只需要考虑 00:00 到 23:59 范围内的持续时间,您可以使用“partial”

hh
说明符而不是
HH
:

var pattern = DurationPattern.CreateWithInvariantCulture("hhmm")
var result = pattern.Parse("1234");

如果您需要支持比这更多的时间,那就变得很棘手 - 我们基本上需要解析,直到分钟只剩下两个字符,而这不是 Noda Time 目前支持的方法。

如果您需要支持“超过 23 小时,但最多 99 小时”(因此恰好是两位数),那么对于当前架构来说,这至少是“可行的”,但无法轻松地用现有模式来表示。 我已就此事

提出问题

。如果您能提供有关具体要求的反馈,我将不胜感激。

一个选项在字符串分配和潜在报告错误方面都非常糟糕,但它至少允许您使用
IPattern<Duration>

直到 Noda Time 本身有更好的解决方案,那就是自己实现

IPattern<Duration>
来插入一个解析前分离,格式化前删除。这是一个至少具有合理功能的示例:
using NodaTime;
using NodaTime.Text;
using System.Text;

public sealed class HHmmDurationPattern : IPattern<Duration>
{
    private readonly DurationPattern patternWithColons = DurationPattern.CreateWithInvariantCulture("HH:mm");

    public StringBuilder AppendFormat(Duration value, StringBuilder builder) =>
        builder.Append(Format(value));

    public string Format(Duration value)
    {
        string formatted = patternWithColons.Format(value);
        return formatted.Replace(":", "");
    }

    public ParseResult<Duration> Parse(string text)
    {
        // If the input is too short, just let the underlying pattern complain.
        if (text.Length < 2)
        {
            return patternWithColons.Parse(text);
        }
        var textWithColons = text.Substring(0, text.Length - 2) + ":" + text.Substring(text.Length - 2);
        return patternWithColons.Parse(textWithColons);
    }
}

请注意,这

强制总小时数只有 2 位 - 因此它将“12345”解析为“123 小时 45 分钟”。它可能并不理想,但作为临时措施可能会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.