Domanda

Since Sony changed how their trophy server authentication works, I am looking for an alternative solution to approximate trophy dates. The UK Playstation Network website has a string underneath unlocked trophies approximating how long ago trophies were earned. I have the following code:

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;
}

If I have the string Attained:17 months ago underneath one of my trophies, it should take the current month and subtract 17 months. If I have the string Attained:3 hours ago, it should take the current date and subtract 3 hours to approximate an earned date. If I have the string Attained: 5 minutes ago, it should take the current date and subtract 5 minutes to approximate an earned date.

My plan is have this code run as a web service and accompany with a desktop client. I'm unsure of whether I should return a TimeSpan or do just calculate the date directly? Is there a better approach? Not all months are 30 days and some years are more than 365 days (leap years) so doing hard coded calculations won't necessarily work.

È stato utile?

Soluzione

You don't have to worry about some months having 30 days and some not. If you have the timespan you can directly decrement the current date by that span.

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

This can be done in or out of your service, but I would perform it in the service if the actual date is what's needed.

Also you can add a regular expression if you need to add some flexibility later on.

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);
}

Could make unit an enum as well

Altri suggerimenti

Noda Time is a much more flexible framework for working with time and date values than the types provided in the .NET base class library. It includes, among other things, a Period type, which represents some amount of time in elapsed years, months, days, etc. The actual elapsed time represented is unfixed. As you say, some months or years are longer than others, so Period is the type to use if you are not dealing with a fixed amount of time (as opposed to a fixed Duration). A Period can be added to the various date/time types in the Noda Time library.

While you can add and subtract a TimeSpan from a DateTime[Offset], it's not a terribly useful type if you need to deal with units of time longer than hours. Consider using Noda Time for nontrivial time/date computations.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top