由于索尼改变了他们的奖杯服务器认证的工作方式,我正在寻找一种替代奖杯日期的替代解决方案。英国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天(闰年),因此进行硬编码计算不一定有效。
答案 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用于非平凡的时间/日期计算。