关于c#:我如何解析时差作为这样的字符串

How can i parse time difference as string like this

我想分析2个日期时间差,如下所示:

1
2
3
4
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*年))。

C对此有任何功能吗?

1
2
3
4
DateTime dt1
DateTime dt2

TimeSpan span = dt1- dt2;

和上面的分析时间跨度(两个日期时间之间的差异)


这比预期的要困难:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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;
    }
}


以下是一些可能有帮助的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
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。有关详细信息,请参见自定义时间跨度格式字符串。

编辑:asker已经澄清了他想要的是"格式化",而不是"解析",所以我的答案可能不相关。不知道这个答案还有什么问题。

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

2


如果您的输入如下:

1
312 Days 21 Hours 16 Minutes 5 Seconds

答案是否定的。您必须自己分析字符串并初始化日期时间变量。简单明了的C日期时间教程。

初始化之后,您可以很容易地在这些日期时间之间进行减法运算。日期时间差的链接。

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

1
312 Days 21 Hours 16 Minutes 5 Seconds

从日期时间差中很容易得到日期、月份等,例如:

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


1
2
3
4
5
6
7
8
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" :"");
}