繁体   English   中英

DateTime.TryParse 世纪控件 C#

[英]DateTime.TryParse century control C#

以下片段的结果是“12/06/1930 12:00:00”。 我如何控制隐含的世纪,使“12 Jun 30”变为 2030?

string dateString = "12 Jun 30"; //from user input
DateTime result;
DateTime.TryParse(dateString, new System.Globalization.CultureInfo("en-GB"),System.Globalization.DateTimeStyles.None,out result);
Console.WriteLine(result.ToString());

请暂时搁置一个事实,即正确的解决方案是首先正确指定日期。

注意:结果与运行代码的 pc 的系统日期时间无关。

答:谢谢 Deeksy

for (int i = 0; i <= 9; i++)
{
    string dateString = "12 Jun " + ((int)i * 10).ToString();
    Console.WriteLine("Parsing " + dateString);
    DateTime result;
    System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-GB");
    cultureInfo.Calendar.TwoDigitYearMax = 2099;
    DateTime.TryParse(dateString, cultureInfo , System.Globalization.DateTimeStyles.None, out result);
    Console.WriteLine(result.ToString());
}

这很棘手,因为TryParse两位数年份的工作方式基于您正在使用的CultureInfo对象的Calendar属性的TwoDigitYearMax属性。 (文化信息->日历-> TwoDigitYearMax)

为了使两位数年份具有20的前缀,您需要手动创建一个CultureInfo对象,该对象的Calendar对象的2099设置为TwoDigitYearMax属性。 不幸的是,这意味着解析的任何两位数字日期都将带有20个前缀(包括98、99等),这可能不是您想要的。

我怀疑您最好的选择是使用第三方日期解析库,而不是使用+ 50 / -50年规则的2位数字年份的标准tryparse。 (将两位数的年份转换为今年之前的50年到比今年更大的50年之间的范围)。

或者,您可以覆盖日历对象(它是虚拟的)上的ToFourDigitYear方法,并使用该方法实现-50 / + 50规则。

我会写一个可重用的函数:

public static object ConvertCustomDate(string input)
{
    //Create a new culture based on our current one but override the two
    //digit year max.
    CultureInfo ci = new CultureInfo(CultureInfo.CurrentCulture.LCID);
    ci.Calendar.TwoDigitYearMax = 2099;
    //Parse the date using our custom culture.
    DateTime dt = DateTime.ParseExact(input, "MMM-yy", ci);
    return new { Month=dt.ToString("MMMM"), Year=dt.ToString("yyyy") };
}

这是我的准日期字符串列表

List<string> dates = new List<string>(new []{
    "May-10",
    "Jun-30",
    "Jul-10",
    "Apr-08",
    "Mar-07"
});

像这样扫描它:

foreach(object obj in dates.Select(d => ConvertCustomDate(d)))
{
    Console.WriteLine(obj);
}

请注意,到2030年,它现在处理的是30,而不是1930 ...

您正在寻找Calendar.TwoDigitYearMax属性

乔恩·斯基特(Jon Skeet)在此贴了一些内容,您可能会觉得有用。

我有一个类似的问题,我用正则表达式解决了。 在您的情况下,它看起来像这样:

private static readonly Regex DateRegex = new Regex(
@"^[0-9][0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9][0-9]$",
RegexOptions.Compiled | RegexOptions.ExplicitCapture);

private static string Beautify(string date)
{
    var match = DateRegex.Match(date);
    if (match.Success)
    {
        // Maybe further checks for correct day
        return date.Insert("dd-MMM-".Length, "20");
    }

    return date;
}

恭喜,您遇到了 Y2K 错误。

此行为的文档以自定义日期和时间格式字符串开头,其中包括yy格式说明符的描述 具体来说,我们有这段摘录:

在解析操作中,根据格式提供程序当前日历的 Calendar.TwoDigitYearMax 属性解释使用“yy”自定义格式说明符解析的两位数年份。

按照Calendar.TwoDigitYearMax文档,我们发现:

此属性允许将 2 位数年份正确转换为 4 位数年份。 例如,如果此属性设置为 2029,则 100 年的范围是从 1930 年到 2029 年。因此,2 位数的值 30 被解释为 1930,而 2 位数的值 29 被解释为 2029。

此属性的初始值源自控制面板的区域和语言选项部分中的设置。

如果您只有两位数代表年份,您将需要猜测当前和上一个世纪或当前和下一个世纪之间的转折点。 微软做出了他们的猜测,但也选择使其可配置,不同的系统可能以不同的方式配置它。 这意味着依赖两位数的年份值是危险的,正如我们在 1999 年之前就知道的那样。自 1999 年以来,没有人再使用两位数来表示年份。

附带说明一下,自从第一次决定以来已经有一段时间了; 微软可能已经过了更新默认猜测的时间(可能是 2079 年,或者完全是一种新方法,可能基于与当年的偏移量)。 不幸的是,从统计数据上可以肯定,有些程序依赖于默认设置不变,因此 Microsoft 很难对其进行更新。 这会导致他们所谓的“破坏性变化”,并且他们非常擅长避免对人们这样做......尽管有一些关于改变这一点的讨论 for.Net 8。

因此,这种情况可能会在不久的将来更频繁地出现,并且找到我的方法是因为它确实出现在另一个地方我觉得值得为这个较旧的问题添加一个更新的答案。 除了确认情况没有(尚未)改变之外,这个答案并没有什么新鲜事。 也许 Windows 11 版本会有一个新的默认值?

result = year.ToString().Length == 1 
      || year.ToString().Length == 2 ? "1" 
       : (Convert.ToInt32(year.ToString()
          .Substring(0, (year.ToString().Length - 2))) + 1).ToString();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM