2008-11-17 9 views
3

Compte tenu d'un nombre de jours, disons 25, le convertir en un texte de durée telle que « 3 semaines, 4 jours »Converting Jours dans Durée Human Readable Texte

C# et F # solutions seraient tous deux Si la F # variation offre une amélioration sur C#.

Modifier: La solution devrait s'étendre au fil des semaines pour inclure des mois et des années. Points bonus pour inclure les siècles et ainsi de suite. Bonus supplémentaire s'il est quelque peu configurable, ce qui signifie que vous pouvez dire à la méthode d'exclure la normalisation des semaines.

Répondre

1

Ceci est une solution récursive. Notez qu'une durée n'a de sens que par rapport à un moment particulier d'un calendrier donné, car les durées des mois et des années varient. Mais voici une solution simple en supposant des longueurs fixes:

let divmod n m = n/m, n % m  

let units = [ 
    ("Centuries", TimeSpan.TicksPerDay * 365L * 100L); 
    ("Years", TimeSpan.TicksPerDay * 365L); 
    ("Weeks", TimeSpan.TicksPerDay * 7L); 
    ("Days", TimeSpan.TicksPerDay) 
] 

let duration days = 
    let rec duration' ticks units acc = 
     match units with 
     | [] -> acc 
     | (u::us) -> 
      let (wholeUnits, ticksRemaining) = divmod ticks (snd u) 
      duration' ticksRemaining us (((fst u), wholeUnits) :: acc) 
    duration' (TimeSpan.FromDays(float days).Ticks) units [] 
5
String.Format("{0} Weeks, {1} days", days/7, days % 7); 
+0

Peut-être qu'une logique de base peut être ajoutée. Par exemple. il suffit de le compter en jours si les jours sont <6, sans ajouter de s si vous n'utilisez pas de pluriel (ou remplacez s par '(s)'). – Brian

0
public class UnitOfMeasure { 
     public UnitOfMeasure(string name, int value) { 
      Name = name; 
      Value = value; 
     } 

     public string Name { get; set; } 
     public int Value { get; set; } 

     public static UnitOfMeasure[] All = new UnitOfMeasure[] { 
      new UnitOfMeasure("Year", 356), 
      new UnitOfMeasure("Month", 30), 
      new UnitOfMeasure("Week", 7), 
      new UnitOfMeasure("Day", 1) 
     }; 

     public static string ConvertToDuration(int days) { 
      List<string> results = new List<string>(); 

      for (int i = 0; i < All.Length; i++) { 
       int count = days/All[i].Value; 

       if (count >= 1) { 
        results.Add((count + " " + All[i].Name) + (count == 1 ? string.Empty : "s")); 
        days -= count * All[i].Value; 
       } 
      } 

      return string.Join(", ", results.ToArray()); 
     } 
    } 
0

est ici une version F # sur la base précédemment affiché la version C#. La principale différence est qu'elle est applicative plutôt qu'impérative (pas de variable mutable).

#light 
let conversions = [| 
    365, "Year", "Years" 
    30, "Month", "Months" 
    7, "Week", "Weeks" 
    1, "Day", "Days" |] 
let ToDuration numDays = 
    conversions 
    |> Array.fold_left (fun (remainDays,results) (n,sing,plur) -> 
     let count = remainDays/n 
     if count >= 1 then 
      remainDays - (count * n), 
       (sprintf "%d %s" count (if count=1 then sing else plur)) :: results 
     else 
      remainDays, results 
    ) (numDays,[]) 
    |> snd |> (fun rs -> System.String.Join(", ", List.rev rs |> List.to_array)) 
printfn "%s" (ToDuration 1008)