【问题标题】:How can i parse time difference as string like this [closed]我如何将时差解析为这样的字符串[关闭]
【发布时间】:2012-12-29 23:28:27
【问题描述】:

我想解析 2 个 DateTime 差异,如下所示:

312 Days 21 Hours 16 Minutes 5 Seconds // there is difference > days
21 Hours 16 Minutes 5 Seconds // there is difference > hours
16 Minutes 5 Seconds // there is difference > minutes
5 Seconds // there is difference < minutes

因此,如果天数以上有差异,它将解析天数,如果小时数以上存在差异,它将解析小时数,依此类推。如果年份不同,我仍然希望它解析为天数(天数差异 + (365*year))

C# 有这方面的功能吗?

DateTime dt1
DateTime dt2

TimeSpan span = dt1- dt2;

和上面一样解析TimeSpan(2个DateTimes之间的差异)

【问题讨论】:

  • 您想从我们这里得到什么?给你写?
  • 你为什么将TimeSpan变量存储为这样的字符串?使用数据库!
  • @ColeJohnson 正则表达式是为了什么?
  • 你的意思是你有两个DateTime,并且你已经减去了它们,但是现在你需要一个格式字符串,它会按照你指示的方式输出结果TimeSpan?还是您输入的字符串表示形式,并且您要创建 TimeSpan 值?
  • 在所有答案/赞成/反对之后,问题变成了 TimeSpan.ToCustomString() 多么糟糕的问题......

标签: c# string parsing datetime datetime-format


【解决方案1】:

这可能会有所帮助:

string[] formats = {
  "d' Days 'h' Hours 'm' Minutes 's' Seconds'",
  "h' Hours 'm' Minutes 's' Seconds'",
  "m' Minutes 's' Seconds'",
  "s' Seconds'",
  "d' Days 'h' Hours 'm' Minutes'",
  "d' Days 'h' Hours 's' Seconds'",
  "d' Days 'm' Minutes 's' Seconds'",
  "h' Hours 'm' Minutes'",
  "h' Hours 's' Seconds'",
  };

var result = TimeSpan.ParseExact(yourString, formats, CultureInfo.CurrentCulture);

如果您担心yourString 有时可能是非法的,还有TryParseExact。详情请见Custom TimeSpan Format Strings

编辑: Asker 澄清说他确实想要“格式化”,而不是“解析”,所以我的回答可能不相关。不知道这个答案还有什么问题。

现在,这是一个(未经测试的)解决方案。零部分被删除,不仅当最重要的部分为零时,而且“中间”的零部分 (01:00:01)。语法(复数和单数)应该没问题。中间和末端的空格应该是正确的。放入static类(扩展方法):

public static string ToMyString(this TimeSpan ts)
{
  if (ts < TimeSpan.Zero)
    throw new ArgumentOutOfRangeException();

  var parts = new List<string>();
  AddPart(parts, ts.Days, "Day");
  AddPart(parts, ts.Hours, "Hour");
  AddPart(parts, ts.Minutes, "Minute");
  AddPart(parts, ts.Seconds, "Second");

  if (parts.Count == 0)
    return "0";

  return string.Join(" ", parts);
}

static void AddPart(List<string> parts, int number, string name)
{
  if (number == 1)
    parts.Add("1 " + name);
  else if (number > 1)
    parts.Add(string.Format("{0} {1}s", number, name));        
}

【讨论】:

  • 现在有一些我以前从未见过的东西!太棒了!
  • 现在有些东西不工作了。
  • @lazyberezovsky 你真的试过我的代码了吗?会发生什么?
  • @JeppeStigNielsen 感谢您的回答。我放弃了投票。
  • 但是你的字符串是什么?
【解决方案2】:

这比预期的要困难:

List<string> timespanStrings = new List<string>() { 
    "312 Days 21 Hours 16 Minutes 5 Seconds", "21 Hours 16 Minutes 5 Seconds",
    "16 Minutes 5 Seconds", "5 Seconds"
};
List<TimeSpan> timespans = new List<TimeSpan>();
foreach (string tsString in timespanStrings)
{
    List<Tuple<int, string>> pairs = new List<Tuple<int, string>>();
    var tokens = tsString.Split();
    if (tokens.Length % 2 == 0)
    {
        int duration;
        for (int i = 0; i < tokens.Length; i += 2)
        {
            string dur = tokens[i];
            string unit = tokens[i + 1];
            if (int.TryParse(dur, out duration))
            {
                pairs.Add(Tuple.Create(duration, unit));
            }
            else // invalid string
                break;
        }
    }

    // create the TimeSpan from the pair
    switch (pairs.Count)
    {
        case 4:  // days
            {
                var dayPair = pairs.First(p => p.Item2.Equals("Days", StringComparison.OrdinalIgnoreCase));
                TimeSpan ts = TimeSpan.FromDays(dayPair.Item1);
                var hourPair = pairs.First(p => p.Item2.Equals("Hours", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsHour = TimeSpan.FromHours(hourPair.Item1);
                var minPair = pairs.First(p => p.Item2.Equals("Minutes", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsMin = TimeSpan.FromMinutes(minPair.Item1);
                var secPair = pairs.First(p => p.Item2.Equals("Seconds", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsSec = TimeSpan.FromSeconds(secPair.Item1);
                ts = ts + tsHour + tsMin + tsSec;
                timespans.Add(ts);
                break;
            }
        case 3:  // hours
            {
                var hourPair = pairs.First(p => p.Item2.Equals("Hours", StringComparison.OrdinalIgnoreCase));
                TimeSpan ts = TimeSpan.FromHours(hourPair.Item1);
                var minPair = pairs.First(p => p.Item2.Equals("Minutes", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsMin = TimeSpan.FromMinutes(minPair.Item1);
                var secPair = pairs.First(p => p.Item2.Equals("Seconds", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsSec = TimeSpan.FromSeconds(secPair.Item1);
                ts = ts + tsMin + tsSec;
                timespans.Add(ts);
                break;
            }
        case 2:  // minutes
            {
                var minPair = pairs.First(p => p.Item2.Equals("Minutes", StringComparison.OrdinalIgnoreCase));
                TimeSpan ts = TimeSpan.FromMinutes(minPair.Item1);
                var secPair = pairs.First(p => p.Item2.Equals("Seconds", StringComparison.OrdinalIgnoreCase));
                TimeSpan tsSec = TimeSpan.FromSeconds(secPair.Item1);
                ts = ts + tsSec;
                timespans.Add(ts);
                break;
            }
        case 1:  // seconds
            timespans.Add(TimeSpan.FromSeconds(pairs[0].Item1));
            break;
        default: 
            break;
    }
}

【讨论】:

  • 我认为这不是 OP 想要的。我猜他只想格式化 TimeSpan。查看 Jeppe Stig Nielsen 的评论
  • @L.B 你是对的。我想解析 TimeSpan :)
  • @MonsterMMORPG:解析TimeSpans的意思是:取一个字符串并创建一个TimeSpan。这就是我的代码所做的。有人愿意解释否决票吗?
  • @TimSchmelter 感谢您的回答。我放弃了投票:)
【解决方案3】:
public static string ToFullString(this TimeSpan timeSpan)
{
    return
        (timeSpan.Days > 0 ? timeSpan.Days + " Days" : "") +
        (timeSpan.Hours > 0 ? " " + timeSpan.Hours + "Hours " : "") +
        (timeSpan.Minutes > 0 ? " " + timeSpan.Minutes + "Minutes " : "") +
        (timeSpan.Seconds > 0 ? " " + timeSpan.Seconds + "Seconds" : "");
}

【讨论】:

  • @cole:伙计,编辑所有帖子怎么样?无聊?
  • 我无事可做
  • @David 的编辑是正确的(代码和输出字符串的格式都很差)。还有一个关于解析的问题,而不是关于转换为字符串的问题。
  • 辛苦了。空格可能会有一些问题。另外,如果timeSpan 小于一秒,我认为空字符串不是正确的输出。
  • @JeppeStigNielsen 你是对的。如果不到一秒,它应该解析为 0。这个函数看起来非常有用,如果 year > 0 将其转换为天,则需要进行更多调整
【解决方案4】:

如果你的输入是这样的:

312 Days 21 Hours 16 Minutes 5 Seconds

答案是否定的。您必须自己解析字符串并初始化 DateTime 变量。 Simple and clear DateTime tutorial for c#

初始化后,您可以轻松地在这些日期时间之间进行减法。 Link for DateTime difference.

如果你想用你以前的样式再次打印出差异:

312 Days 21 Hours 16 Minutes 5 Seconds

很容易从 DateTimeDifference 中获取 Days、Month 等,例如:

DateTime yourDateTime = foo;
int month = yourDateTime.Month;

【讨论】:

  • 谢谢我放弃投票给你
猜你喜欢
  • 1970-01-01
  • 2013-07-18
  • 1970-01-01
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 2022-01-20
相关资源
最近更新 更多