如何优雅提取字符串中任意位置的YYYYmmDD格式日期?
问题:提取字符串中YYYYMMDD格式的日期
我有一个包含YYYYMMDD格式日期的字符串,日期位置不固定,还夹杂其他数字序列,示例如下:
xx12x20240113yyyy123zzzz 20240201xxxx34yyy xxxxxx20240315yyy1224zzz
目前我通过循环逐个测试数字序列来提取日期,但希望找到更简洁优雅的方法。当前使用的C#代码如下:
private bool InvoiceData(string Filename, out string Invoice, out String InvoiceDate, out string Error) { bool Esito = false; Invoice = ""; InvoiceDate = ""; Error = ""; try { int nPos = 0; int nPos2 = 0; string sTemp = Filename; string sTemp2 = ""; while ((nPos = sTemp.IndexOfAny("0123456789".ToCharArray())) >= 0) { sTemp2 = sTemp.Substring(nPos, 8); if (sTemp2.All(char.IsNumber)) { string[] formats = { "yyyyMMdd" }; if (InvoiceDate == "" && DateTime.TryParseExact(sTemp2, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dDataFattura)) { InvoiceDate = dDataFattura.ToString("yyyyMMdd"); } } else { if (Invoice == "") { nPos2 = sTemp.Substring(nPos).IndexOf("_"); // This is by Design Invoice = Filename.Substring(nPos, nPos2); } } nPos2 = 0; while (Char.IsDigit(sTemp2[nPos2++]) && nPos2 < sTemp2.Length) { } sTemp = sTemp.Substring(nPos + nPos2); } if (InvoiceDate != "" && Invoice != "") { Esito = true; } } catch (Exception ex) { Error = ex.Message; } return Esito; }
请问是否存在更简洁的方式提取该格式的日期?
更简洁的实现方案
可以用正则表达式配合日期验证来实现,代码更简洁易读,逻辑也更清晰:
核心思路
- 用正则匹配字符串中所有连续的8位数字(
\d{8}),这些是潜在的YYYYMMDD格式日期 - 对每个匹配结果,用
DateTime.TryParseExact验证是否为合法日期 - 提取第一个符合要求的日期(或所有符合的,根据需求调整)
优化后的代码
using System.Text.RegularExpressions; using System.Globalization; private bool InvoiceData(string filename, out string invoice, out string invoiceDate, out string error) { invoice = string.Empty; invoiceDate = string.Empty; error = string.Empty; try { // 提取第一个符合YYYYMMDD格式的日期 var dateMatches = Regex.Matches(filename, @"\d{8}"); foreach (Match match in dateMatches) { if (DateTime.TryParseExact(match.Value, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date)) { invoiceDate = date.ToString("yyyyMMdd"); break; // 找到第一个有效日期就停止 } } // 提取Invoice(用正则简化原逻辑) var invoiceMatch = Regex.Match(filename, @"\d+_"); if (invoiceMatch.Success) { invoice = invoiceMatch.Value.TrimEnd('_'); } return !string.IsNullOrEmpty(invoice) && !string.IsNullOrEmpty(invoiceDate); } catch (Exception ex) { error = ex.Message; return false; } }
代码说明
- 日期提取:正则
\d{8}直接定位所有8位数字序列,避免了手动循环查找数字的繁琐;通过TryParseExact确保只有合法的YYYYMMDD格式日期会被提取 - Invoice提取:用正则
\d+_匹配数字加下划线的序列,直接提取数字部分,替代原代码中手动查找索引的逻辑,更简洁 - 整体代码去掉了复杂的循环索引操作,可读性和维护性大幅提升
内容的提问来源于stack exchange,提问作者user24145613
相关产品推荐
相关产品推荐

