2

我正在写这个问题,因为我正在寻求最好的方法来做到这一点。我的程序中有很多这些,我想创建一个方法来将包含一秒计时器的 Int32 转换为格式良好的字符串。

因此,例如,如果我的计时器 int 是在让我们说一个像 16429 这样的随机数,它将是:

4 hours, 32 minutes and 9 seconds

如果是 600,它将是:

10 minutes

如果是60,那就是

1 minute

如果是 172801,它将是

2 days and 1 second

如果是32,那就是

32 seconds

我希望每个单词末尾的 "s" 像 "minute"、"second" 和 "day" 只在它不等于 1 时才放 S,因此实际上不需要正确发音. 我也只希望在需要时添加天数和小时数以及其他内容,因此如果计时器以秒为单位低于 1 天,它只会显示小时、分钟和秒,或者需要什么。

实现这样的目标的最佳方法是什么?我在下面有这个功能,但它非常混乱,最多只能达到几分钟和几秒钟,而不是几小时或几天:

public static string GetConvertedTime(int timer)
{
    int Minutes = timer / 60;
    int Seconds = timer - Minutes * 60;

    if (timer < 60)
    {
        string secs = (Seconds != 1) ? "s" : "";
        return "" + timer + " second" + secs;
    }

    else
    {
        if (Seconds < 1)
        {
            string mins = (Minutes != 1) ? "s" : "";
            return "" + Minutes + " minute" + mins;
        }
        else
        {
            string mins = (Minutes != 1) ? "s" : "";
            string secs = (Seconds != 1) ? "s" : "";
            return "" + Minutes + " minute" + mins + " and " + Seconds + " second" + secs;
        }
    }
}

这样做的最佳方法到底是什么?

4

3 回答 3

4

“最佳方式”是非常主观的。DRY 通常是最好的,考虑到本地化和非常规复数形式通常是最好的,保持简短和活泼通常是最好的:

public static string FriendlyDuration(int seconds) {
    int[] divisors = { 60 * 60 * 24, 60 * 60, 60 , 1};
    string[] language = { ", ", " and ", "days", "day", "hours", "hour", "minutes", "minute", "seconds", "second"};
    var parts = new List<string>();
    for (int part = 0; part < divisors.Length; ++part) {
        int count = seconds / divisors[part];
        if (count == 0) continue;
        string unit = language[part*2 + (count == 1 ? 3 : 2)];
        parts.Add(string.Format("{0} {1}", count, unit));
        seconds -= count * divisors[part];
    }
    var result = string.Join(language[0], parts.ToArray());
    if (parts.Count > 1) {
        var ix = result.LastIndexOf(language[0]);
        result = result.Substring(0, ix) + language[1] + result.Substring(ix + language[0].Length);
    }
    return result;
}
于 2017-03-06T18:44:17.813 回答
3

可能我能想到的最好的方法是使用TimeSpan这样的:

var time = new TimeSpan(0, 0, timer);
var s = "s";
return $"{time.Days} day{(time.Days != 1 ? s : String.Empty)}, {time.Hours} hour{(time.Hours != 1 ? s : String.Empty)}, {time.Minutes} minute{(time.Minutes != 1 ? s : String.Empty)}, and {time.Seconds} second{(time.Seconds != 1 ? s : String.Empty)}";

如果您需要隐藏空的前导值:

var sb = new StringBuilder();
var s = "s";
var time = new TimeSpan(0, 0, timer);
var continuation = false;
if (time.Days > 0)
{
    sb.Append($"{time.Days} day{(time.Days != 1 ? s : String.Empty)}, ");
    continuation = true;
}
if (time.Hours > 0 || continuation)
{
    sb.Append($"{time.Hours} hour{(time.Hours != 1 ? s : String.Empty)}, ");
    continuation = true;
}
if (time.Minutes > 0 || continuation)
{
    sb.Append($"{time.Minutes} minute{(time.Minutes != 1 ? s : String.Empty)}{(continuation ? "," : String.Empty)} ");
    continuation = true;
}
if (continuation) sb.Append("and ");

sb.Append($"{time.Seconds} second{(time.Seconds != 1 ? s : String.Empty)}");
return sb.ToString();
于 2017-03-06T17:50:06.673 回答
1

你可以试试这个名为Humanizer 的库

于 2017-03-06T17:44:01.973 回答