我有一个相对模糊的要求,但感觉应该可以使用 BCL。
对于上下文,我正在解析Noda Time中的日期/时间字符串。我在输入字符串中为我的位置维护一个逻辑光标。因此,虽然完整的字符串可能是“2013 年 1 月 3 日”,但逻辑光标可能位于“J”。
现在,我需要解析月份名称,将其与文化的所有已知月份名称进行比较:
- 文化敏感
- 不区分大小写
- 只是从光标点开始(不是以后;我想看看光标是否在“查看”候选月份名称)
- 迅速地
- ...然后我需要知道使用了多少个字符
当前执行此操作的代码通常使用CompareInfo.Compare
. 它实际上是这样的(仅用于匹配部分 - 真实的代码更多,但与匹配无关):
internal bool MatchCaseInsensitive(string candidate, CompareInfo compareInfo)
{
return compareInfo.Compare(text, position, candidate.Length,
candidate, 0, candidate.Length,
CompareOptions.IgnoreCase) == 0;
}
但是,这取决于候选对象和我们比较的区域长度相同。大多数时候都很好,但在某些特殊情况下就不行了。假设我们有类似的东西:
// U+00E9 is a single code point for e-acute
var text = "x b\u00e9d y";
int position = 2;
// e followed by U+0301 still means e-acute, but from two code points
var candidate = "be\u0301d";
现在我的比较将失败。我可以使用IsPrefix
:
if (compareInfo.IsPrefix(text.Substring(position), candidate,
CompareOptions.IgnoreCase))
但:
- 这需要我创建一个子字符串,我真的宁愿避免。(我将 Noda Time 视为有效的系统库;解析性能对某些客户可能很重要。)
- 它没有告诉我之后将光标前进多远
实际上,我强烈怀疑这不会经常出现......但我真的很想在这里做正确的事情。我也非常希望能够在不成为 Unicode 专家或自己实现它的情况下做到这一点:)
(在 Noda Time 中作为bug 210提出,以防有人想遵循任何最终结论。)
我喜欢标准化的想法。我需要详细检查 a) 正确性和 b) 性能。假设我可以让它正常工作,我仍然不确定它是否值得全面改变 - 这种事情可能永远不会在现实生活中真正出现,但可能会损害我所有用户的表现: (
我还检查了 BCL - 它似乎也没有正确处理这个问题。示例代码:
using System;
using System.Globalization;
class Test
{
static void Main()
{
var culture = (CultureInfo) CultureInfo.InvariantCulture.Clone();
var months = culture.DateTimeFormat.AbbreviatedMonthNames;
months[10] = "be\u0301d";
culture.DateTimeFormat.AbbreviatedMonthNames = months;
var text = "25 b\u00e9d 2013";
var pattern = "dd MMM yyyy";
DateTime result;
if (DateTime.TryParseExact(text, pattern, culture,
DateTimeStyles.None, out result))
{
Console.WriteLine("Parsed! Result={0}", result);
}
else
{
Console.WriteLine("Didn't parse");
}
}
}
将自定义月份名称更改为仅具有“bEd”文本值的“床”可以很好地解析。
好的,还有几个数据点:
使用
Substring
and的成本很高,IsPrefix
但并不可怕。在我的开发笔记本电脑上的“2013 年 4 月 12 日星期五 20:28:42”示例中,它将我在一秒钟内可以执行的解析操作的数量从大约 460K 更改为大约 400K。如果可能的话,我宁愿避免这种减速,但这还不错。规范化没有我想象的那么可行——因为它在可移植类库中不可用。我可能只将它用于非 PCL 构建,从而允许 PCL 构建不太正确。标准化测试的
string.IsNormalized
性能损失 ( 我仍然不确定它是否能满足我的所有需求——例如,在许多文化中,包含“ß”的月份名称应该与“ss”匹配,我相信……而规范化并不能做到这一点。