Преобразование дней в текст, читаемый человеком - PullRequest
3 голосов
/ 17 ноября 2008

Учитывая количество дней, скажем, 25, преобразуйте его в текст длительности, такой как «3 недели, 4 дня»

Решения C # и F # были бы хороши, если бы вариант F # предлагал какое-либо улучшение по сравнению с C #.

Изменить: решение должно расширяться за последние недели, чтобы включить месяцы и годы. Бонусные баллы за включение веков и тд. Дополнительный бонус, если он в некоторой степени настраиваемый, то есть вы можете указать этому методу исключение нормализации недель.

Ответы [ 4 ]

5 голосов
/ 17 ноября 2008
String.Format("{0} Weeks, {1} days", days / 7, days % 7);
1 голос
/ 18 ноября 2008

Это рекурсивное решение. Обратите внимание, что продолжительность действительно имеет смысл измерять только для определенного момента времени в данном календаре, потому что длина месяца и года варьируется. Но вот простое решение, предполагающее фиксированную длину:

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 []
0 голосов
/ 18 ноября 2008

Вот версия F #, основанная на ранее опубликованной версии C #. Основное различие заключается в том, что оно скорее обязательное, чем императивное (без изменяемых переменных).

#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)    
0 голосов
/ 18 ноября 2008
    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());
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...