使用 DateTime.TryParseExact 解析非标准日期格式

发布于 2024-12-02 00:58:28 字数 827 浏览 1 评论 0原文

您好,我正在尝试解析“1012012”、“2012 年 1 月 1 日”等日期字符串。

  1. 读取 Api 它说要在日期没有前导 0 的情况下使用 d,%d。无法使其适用于像“1012012”这样的日期

  2. 尝试使用“d MMM YYYY”表示“2012 年 1 月 1 日”,什么我使用“st”、“th”有效吗?

    使用系统;
    使用系统.IO;
    使用系统全球化;
    
    命名空间测试
    {
      类脚本
      {
        静态公共无效主要(字符串[]参数)
        {
    
            //字符串日期字符串 = "9022011"; // q1
            String dateString = "2011 年 2 月 9 日"; //q2
            System.DateTime 日期 = DateTime.MinValue;
            string[] 格式 = { "ddMMyyyy", "d MMM yyyy" }; // 正确的格式字符串是什么?
    
            if (DateTime.TryParseExact(dateString,format,new CultureInfo("en-AU"),DateTimeStyles.None,out date))
                            {
                Console.Out.WriteLine(date.ToString());
            } 
                            别的
                            {
                Console.Out.WriteLine("无法转换");
            }
         }
      }
    
    }
    

Hi Im trying to parse date strings like "1012012", "1st January 2012".

  1. read the Api It says to use d,%d where the date does not have a leading 0. Cant get it working for dates like "1012012"

  2. trying to use "d MMM YYYY" for "1st January 2012", what do I use so 'st', 'th' works?

    using System;
    using System.IO;
    using System.Globalization;
    
    namespace test
    {
      class Script
      {
        static public void Main(string [] args)
        {
    
            //String dateString = "9022011";  // q1
            String dateString = "9th February 2011";  //q2
            System.DateTime date = DateTime.MinValue;
            string[] format = { "ddMMyyyy", "d MMM yyyy" }; // what would be the correct format strings?
    
            if (DateTime.TryParseExact(dateString,format,new CultureInfo("en-AU"),DateTimeStyles.None,out date))
                            {
                Console.Out.WriteLine(date.ToString());
            } 
                            else
                            {
                Console.Out.WriteLine("cant convert");
            }
         }
      }
    
    }
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心奴独伤 2024-12-09 00:58:28
var dateString = "1st February 2011";
DateTime date;
var replaced = dateString.Substring(0,4)
                         .Replace("nd","")
                         .Replace("th","")
                         .Replace("rd","")
                         .Replace("st","")
                         + dateString.Substring(4);

DateTime.TryParseExact(replaced, "d MMMM yyyy",
                       new CultureInfo("en-us"), DateTimeStyles.AssumeLocal, 
                       out date);

应该可以解决这个问题(抱歉,“th”很讨厌)-你必须小心对待 st(八月)-只需将其从前几次出现中删除即可:

var dateString = "1st February 2011";
DateTime date;
var replaced = dateString.Substring(0,4)
                         .Replace("nd","")
                         .Replace("th","")
                         .Replace("rd","")
                         .Replace("st","")
                         + dateString.Substring(4);

DateTime.TryParseExact(replaced, "d MMMM yyyy",
                       new CultureInfo("en-us"), DateTimeStyles.AssumeLocal, 
                       out date);

should do the trick (sorry the 'th' is nasty) - you have to take some care with the st (August) - just remove it only from the first few appearances:

童话里做英雄 2024-12-09 00:58:28
  1. 我认为这是不可能的。解析器从左到右处理您的输入,因此如果它看到“1012012”,它会认为日期是 10,然后解析失败,因为没有足够的字符,即使格式字符串是“dMMyyyy”。需要某种回溯来考虑这一天为 1 的可能性,但不幸的是,它似乎并没有这样做。

    然而,使用自定义正则表达式来解析此格式相当简单。正则表达式解析器确实使用回溯,因此它会正确考虑这两个选项:

    字符串输入 = "1012012";
    匹配 m = Regex.Match(input, @"^(?<日>\d{1,2})(?<月>\d{2})(?<年>\d{4}) $");
    if( m. 成功 )
    {
        DateTime d = new DateTime(Convert.ToInt32(m.Groups["year"].Value),
                                  Convert.ToInt32(m.Groups["month"].Value),
                                  Convert.ToInt32(m.Groups["day"].Value));
    }
    

    如果字符串的长度为七,另一种选择是简单地添加前导零:

    字符串输入 = "1012012";
    if( 输入. 长度 == 7 )
        输入=“0”+输入;
    DateTime d = DateTime.ParseExact(input, "ddMMyyyy", CultureInfo.CurrentCulture);
    
  2. 而不是像其他答案中那样尝试进行多次查找和替换,您可以利用字符串的确切格式已知这一事实。它以一位或两位数字开头,后跟两个字母,然后是月份和年份。所以你可以像这样提取日期:

    字符串输入 = "2012 年 1 月 1 日";
    int 索引 = char.IsNumber(input, 1) ? 2:1;
    输入 = input.Substring(0, 索引) + input.Substring(索引 + 2);
    DateTime d = DateTime.ParseExact(input, "d MMMM yyyy", CultureInfo.InvariantCulture);
    

    当然,这将接受在这些位置上纯粹无意义的日期,例如“1xx 2012 年 1 月”,但我不确定这在您的情况下是否存在问题。

    如果输入可以包含非英语月份名称,还请务必传递适当的CultureInfo

如果您可以在不事先知道要获得哪种格式的情况下获得任一格式,则需要进行简单的检查以了解事先使用哪种方法。第一种格式的字符串始终为 7 或 8 个字符,而第二种格式的字符串始终更长,因此这应该很容易测试。另一种方法是检查字符串是否包含任何非数字字符(在这种情况下为长格式)。

  1. I don't think this can be done. The parser processes your input left-to-right, so if it sees "1012012" it will think the day is 10, and then fail the parse because there's not enough characters left, even if the format string is "dMMyyyy". It would need some kind of backtracking to consider the possibility that the day is 1, but it doesn't seem to do that unfortunately.

    It is however fairly simple to use a custom regex to parse this format. The regex parser does use backtracking so it will correctly consider both options:

    string input = "1012012";
    Match m = Regex.Match(input, @"^(?<day>\d{1,2})(?<month>\d{2})(?<year>\d{4})$");
    if( m.Success )
    {
        DateTime d = new DateTime(Convert.ToInt32(m.Groups["year"].Value),
                                  Convert.ToInt32(m.Groups["month"].Value),
                                  Convert.ToInt32(m.Groups["day"].Value));
    }
    

    Another option would be to simple add a leading zero if the length of the string is seven:

    string input = "1012012";
    if( input.Length == 7 )
        input = "0" + input;
    DateTime d = DateTime.ParseExact(input, "ddMMyyyy", CultureInfo.CurrentCulture);
    
  2. Rather than attempting to do multiple find and replaces as in the other answers, you can use the fact that the exact format of the string is known. It starts with one or two digits, followed by two letters, followed by the month and the year. So you could extract the date like this:

    string input = "1st January 2012";
    int index = char.IsNumber(input, 1) ? 2 : 1;
    input = input.Substring(0, index) + input.Substring(index + 2);
    DateTime d = DateTime.ParseExact(input, "d MMMM yyyy", CultureInfo.InvariantCulture);
    

    Of course, this will accept dates that have pure nonsense in those positions, like "1xx January 2012", but I'm not sure if that's a problem in your case.

    Also be sure to pass the appropriate CultureInfo if the input can hold non-English month names.

If you can get either format without knowing in advance which you're getting, you'll need a simple check to see which method to use beforehand. Strings in the first format will always be 7 or 8 characters, and strings in the second format will always be longer, so this should be easy to test. Another method would be to check if the string contains any non-numeric characters (in which case it's the long format).

時窥 2024-12-09 00:58:28

如果您想解析特定于区域性的日期字符串,您应该使用匹配的区域性。 CultureInfo.InvariantCulture 不是一个好主意,因为它只适用于英文字符串。
但是,您想要做的事情仅使用格式说明符是不可能的,因为当天没有可以解析“th”、“st”等字符串的方法。您必须事先手动删除它们。

If you want to parse culture specific date strings you should use a matching culture. CultureInfo.InvariantCulture isn't a good idea, because it will only work with English strings.
However, what you are trying to do is not possible only with format specifiers, because there is no for the day that can parse the "th", "st" etc. strings. You will have to remove them manually beforehand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文