【问题标题】:c# How to extract just the format from a string containing a format (e.g. string = "Printed on {0:dd MMM yyyy}" and I want dd MMM yyyyc# 如何从包含格式的字符串中提取格式(例如 string = "Printed on {0:dd MMM yyyy}" 我想要 dd MMM yyyy
【发布时间】:2020-04-06 00:51:55
【问题描述】:

如果我有一个包含格式的字符串,例如下面(注意我不能改变这个字符串格式)

var str = "FormatedDate:Printed {0:dd MMM yyyy HH:mm:ss}"

我只需要提取格式,例如

"dd MMM yyyy HH:mm:ss"

我知道我可以使用字符串操作或正则表达式来做到这一点,但有没有.Net 方法可以使用string/format 等来做到这一点。例如而不是将给定的字符串插入到我需要提取该格式的格式中。

非常感谢

【问题讨论】:

  • 我不相信 .Net 提供了魔法。如果你有一个非泛型的字符串(比如你的),你将不得不做一些字符串操作来得到你需要的东西。
  • 在这里使用正则表达式有什么低效的地方?您至少可以使用它来解析日期时间数据,然后将字符串操作为 .NET 可以实际解析为 DateTime 对象的内容。
  • 谁说我要解析成 DateTime 对象?我只是想知道是否有一种方法可以提取它,因为 .Net 使用该格式将其应用于插值字符串 - 所以也许可以访问它。如果不是很好,我将使用正则表达式/字符串操作。
  • 请问您为什么需要这样做?
  • 我拿了一个json 文件,其中包含(在许多其他内容中)一些字段,例如"FormatedDate:Printed {0:dd MMM yyyy HH:mm:ss}"。我需要将此(实际上是使用插值字符串的任何组合)转换为使用 thymeleaf 表示日期的 HTML 文档(例如<p class="footer-left" th:text="${#dates.format(#dates.createNow(), 'dd MMM yyyy HH:mm:ss')}" />,谢谢

标签: c# .net string datetime format


【解决方案1】:

您可以使用string.Format() 提取所有使用的格式列表,并传入您专门编写的IFormattable 对象列表以记录所使用的格式。

/// <summary>
/// A detected argument in a format string
/// </summary>
public class DetectedFormat
{
    public DetectedFormat(int position, string format)
    {
        Position = position;
        Format = format;
    }

    public int Position { get; set; }
    public string Format { get; set; }
}


/// <summary>
/// Implements IFormattable. Used to collect format placeholders
/// </summary>
public class FormatDetector: IFormattable
{
    private int _position;
    List<DetectedFormat> _list;

    public FormatDetector(int position, List<DetectedFormat> list)
    {
        _position = position;
        _list = list;
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        DetectedFormat detectedFormat = new DetectedFormat(_position, format);
        _list.Add(detectedFormat);

        // Return the placeholder without the format
        return "{" + _position + "}";
    }
}

示例代码

// Max index of arguments to support
int maxIndex = 20;

string f = "Text {1:-3} with {0} some {2:0.###} format {0:dd MMM yyyy HH:mm:ss} data";

// Empty list to collect the detected formats
List<DetectedFormat> detectedFormats = new List<DetectedFormat>();

// Create list of fake arguments
FormatDetector[] argumentDetectors = (from i in Enumerable.Range(0, maxIndex + 1)
                                        select new FormatDetector(i, detectedFormats)).ToArray();

// Use string.format with fake arguments to collect the formats
string strippedFormat = string.Format(f, argumentDetectors);

// Output format string without the formats
Console.WriteLine(strippedFormat);

// output info on the formats used
foreach(var detectedFormat in detectedFormats)
{
    Console.WriteLine(detectedFormat.Position + " - " + detectedFormat.Format);
}

输出:

文本 {1} 与 {0} 一些 {2} 格式 {0} 数据
1 - -3
0 -
2 - 0.###
0 - dd MMM yyyy HH:mm:ss

【讨论】:

  • 这很完美,正是我所要求的。谢谢
【解决方案2】:

使用正则表达式

            string str = "FormatedDate:Printed {0:dd MMM yyyy HH:mm:ss}";
            string pattern = @"{\d+:(?'date'[^}]+)";
            Match match = Regex.Match(str, pattern);
            string date = match.Groups["date"].Value;

没有正则表达式

            string str = "FormatedDate:Printed {0:dd MMM yyyy HH:mm:ss}";

            string[] splitData = str.Split(new char[] { '{' });
            string date = splitData[1].Substring(splitData[1].IndexOf(":") + 1);
            date = date.Replace("}", "");

同时拆分开闭大括号节省了一行代码

            string str = "FormatedDate:Printed {0:dd MMM yyyy HH:mm:ss}";

            string[] splitData = str.Split(new char[] { '{', '}' });
            string date = splitData[1].Substring(splitData[1].IndexOf(":") + 1);

【讨论】:

  • 他要求一种不包括正则表达式的方式。当然,我倾向于同意这是一个可靠的解决方案,我们不应该重新发明轮子。
  • 我添加了一个非正则表达式解决方案。
  • 这也是我的解决方案,但我不想挖走你,哈哈。这也是非常好的代码。我可以告诉你,你已经这样做了很长时间了。
猜你喜欢
  • 1970-01-01
  • 2018-04-30
  • 2016-07-06
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多