从近似时间跨度计算近似日期

时间:2013-11-12 01:42:57

标签: c# date date-arithmetic

由于索尼改变了他们的奖杯服务器认证的工作方式,我正在寻找一种替代奖杯日期的替代解决方案。英国Playstation Network网站在解锁奖杯下方有一个字符串,近似于多久以前获得的奖杯。我有以下代码:

private TimeSpan ParseTimeSpan(string datestring)
{
    TimeSpan ts = new TimeSpan();
    datestring = datestring.Replace("Attained:", ""); // strip Attained:
    string[] parts = datestring.Split(' ');
    int numeric = int.Parse(parts[0]);
    string duration = parts[1];
    switch(duration)
    {
        case "minutes":
            ts = new TimeSpan(0, numeric, 0);
            break;
        case "hours":
            ts = new TimeSpan(numeric, 0, 0);
            break;
        case "days":
            ts = new TimeSpan(numeric, 0, 0, 0);
            break;
        case "months":
            ts = new TimeSpan(numeric * 30, 0, 0);
            break;
        case "years":
            ts = new TimeSpan(numeric * 365, 0, 0);
            break;
    }
    return ts;
}

如果我的一个奖杯下面有字符串Attained:17 months ago,那么它应该占用当前月份并减去17个月。如果我有字符串Attained:3 hours ago,则应使用当前日期并减去3小时以估算获得的日期。如果我有字符串Attained: 5 minutes ago,则应该使用当前日期并减去5分钟来估算获得的日期。

我的计划是将此代码作为Web服务运行,并伴随桌面客户端。我不确定是否应该返回TimeSpan或直接计算日期?有更好的方法吗?并非所有月份都是30天,有些年份超过365天(闰年),因此进行硬编码计算不一定有效。

2 个答案:

答案 0 :(得分:1)

您不必担心有几个月有30天而有些则没有。如果你有时间跨度,你可以直接递减当前日期。

TimeSpan ts = new TimeSpan(5,0,0);
var earned = DateTime.Now - ts;
Console.Write(earned);

这可以在您的服务内外完成,但如果实际日期是您需要的话,我会在服务中执行。

如果您以后需要增加一些灵活性,也可以添加正则表达式。

string input = "Attained:17 months ago";
string pattern = @"Attained:(?<value>[0-9]+) (?<unit>(years|months|days)) ago";
var match = Regex.Match(input, pattern);

if(match.Success)
{
    int value = Int32.Parse(match.Groups["value"].Value);
    string unit = match.Groups["unit"].Value;
    Console.WriteLine(value);
    Console.WriteLine(unit);
}

也可以使单位成为枚举

答案 1 :(得分:1)

Noda Time是一个更灵活的框架,用于处理时间和日期值,而不是.NET基类库中提供的类型。除其他外,它包括Period类型,表示经过的年,月,日等的一些时间。表示的实际经过时间是不固定。正如您所说,某些月份或几年比其他月份更长,因此如果您没有处理固定的时间(而不是固定的Period),Duration是要使用的类型。可以将Period添加到Noda Time库中的各种日期/时间类型。

虽然您可以从TimeSpan添加和减去DateTime[Offset],但如果您需要处理超过小时的时间单位,则它不是非常有用的类型。考虑将Noda Time用于非平凡的时间/日期计算。