有没有一种简洁的方法来实现 TimeSpan 格式的条件复数?
Is There a Concise Way To Achieve Conditional Pluralization of TimeSpan Format?
我有 TimeSpan
跟踪计算时间的对象。 TimeSpan
的范围可以从几秒到几天。我目前有一个相当冗长的方法来给我一个来自 TimeSpan
的字符串,它以长格式表示 TimeSpan
;例如:
3 Days 13 Hours 1 Minute 52 Seconds
当 TimeSpan
小于 1
秒时,我显示 Milliseconds
属性。这个代码很简单,但正如我上面所说的那样非常冗长。有没有一种类似于DateTime.Now.ToString("ddMMyyyy hhmmssffff")
的简洁方法来实现这一点?以下是我当前的代码:
public static string GetLongTime(TimeSpan t) {
string result = string.Empty;
if (t.Days > 0) {
if (t.Days == 1) result = "1 Day";
else result = $"{t.Days} Days";
} else if (t.TotalMilliseconds < 1000) {
if (t.Milliseconds > 0)
result = $"{t.Milliseconds}ms";
} else {
if (t.Hours > 0) {
if (t.Hours == 1) result += "1 Hour ";
else result += $"{t.Hours} Hours ";
}
if (t.Minutes > 0) {
if (t.Minutes == 1) result += "1 Minute ";
else result += $"{t.Minutes} Minutes ";
}
if (t.Seconds > 0) {
if (t.Seconds == 1) result += "1 Second ";
else result += $"{t.Seconds } Seconds ";
}
}
return result;
}
就像 DateTime
一样,TimeSpan
对象有一个 custom format list;然而,他们的示例列表显示带有良好 ol' 时尚 (s)
附加物的字符串:
TimeSpan duration = new TimeSpan(1, 12, 23, 62);
Console.WriteLine("Time of Travel: {0:%d} day(s)", duration);
Console.WriteLine("Time of Travel: {0:dd\.hh\:mm\:ss} days", duration);
Time of Travel: 1 day(s)
Time of Travel: 01.12:24:02 days
这不是我真正想要的。我还在 Whosebug 上查看了一些相关的 posts,正如一位用户在评论中指出的那样,它们是很好的资源。总的来说,这些都不是我正在寻找的解决方案,因为我主要寄希望于一些非常简洁的东西,例如:
return t.ToString("d Day?s");
当然以上只是伪造的,实际上不会做更多的事情:
3 Day?s
一些相关的 post 承诺重构我的代码;例如,this post 推荐条件赋值运算符:
string result = string.Empty;
if (t.Days > 0)
return $"{t.Days} {(t.Days > 1 ? "Days " : "Day ")}";
else if (t.TotalMilliseconds < 1000) {
if (t.Milliseconds > 0)
return $"{t.Milliseconds}ms";
} else {
if (t.Hours > 0)
result += $"{t.Hours} {(t.Hours > 1 ? "Hours " : "Hour ")}";
if (t.Minutes > 0)
result += $"{t.Minutes} {(t.Minutes > 1 ? "Minutes " : "Minute ")}";
if (t.Seconds > 0)
result += $"{t.Seconds} {(t.Seconds > 1 ? "Seconds " : "Second ")}";
}
return result;
虽然这缩短了代码,但它并没有使它看起来最干净(尤其是对于新开发人员而言)。这也符合 post 上的 this post that recommends using a SortedList
of the proper formats; however, I agree with the OP; 您的代码确实需要一些时间才能理解。这是我唯一不喜欢的东西。。
有没有办法在格式字符串中实现条件复数;或者,与我上面的方法相比,是否有更简单和简洁的方法?
.NET 中没有使这成为可能的内置 TimeSpan 格式说明符。
但是,我已经根据需要实现了此功能。它在我的免费开源 utility library 中可用。它是根据 MIT 许可发布的,因此您可以复制代码或将库包含在您的项目中。
用法(选择后一个选项时)
安装 NuGet 包。在程序包管理器控制台中键入以下内容:
Install-Package Karambolo.Common
然后您可以像这样使用 ToTimeReference 扩展方法转换 TimeSpan 值。
using System;
using Karambolo.Common;
using Karambolo.Common.Localization;
class Program
{
static void Main(string[] args)
{
var ts = new TimeSpan(3, 13, 1, 52);
Console.WriteLine(ts.ToTimeReference(4, "{0}", "now", "{0}", DefaultTextLocalizer.Instance));
}
}
上面的代码打印:
3 days 13 hours 1 minute 52 seconds
我在示例代码中使用的 ToTimeReference 重载使您可以完全控制输出的格式。最后一个参数是一个委托,负责指定时间间隔字符串的格式(如 "day"、"hour" 等)。它可用于本地化函数的输出。
这只是一个更短的方法。这里的可读性是一个视角问题:)
一些例子,看看是否符合要求。
TimeSpan ts = new TimeSpan(3, 4, 10, 25);
=> 3 Days 4 Hours 10 Minutes 25 Seconds
TimeSpan ts = new TimeSpan(0, 0, 0, 0, 700);
=> 700ms
TimeSpan ts = new TimeSpan(0, 2, 0, 1, 700);
=> 2 Hours 1 Second
TimeSpan ts = new TimeSpan(1, 1, 1, 1);
=> 1 Day 1 Hour 1 Minute 1 Second
TimeSpan ts = new TimeSpan([Some time span]);
string[] TFormat = new[] {
(ts.Days > 1 ? ts.Days + " Days" : (ts.Days == 1 ? "1 Day" : "")),
(ts.Hours > 1 ? " "+ ts.Hours + " Hours" : (ts.Hours == 1 ? " 1 Hour" : "")),
(ts.Minutes > 1 ? " " + ts.Minutes + " Minutes" : (ts.Minutes == 1 ? " 1 Minute" : "")),
(ts.Seconds > 1 ? " " + ts.Seconds + " Seconds" : (ts.Seconds == 1 ? " 1 Second" : "")),
(ts.TotalMilliseconds < 1000 ? $"{ts.TotalMilliseconds }ms" : "")
};
Console.WriteLine($"{TFormat[0]}{TFormat[1]}{TFormat[2]}{TFormat[3]}{TFormat[4]}".TrimStart());
我有 TimeSpan
跟踪计算时间的对象。 TimeSpan
的范围可以从几秒到几天。我目前有一个相当冗长的方法来给我一个来自 TimeSpan
的字符串,它以长格式表示 TimeSpan
;例如:
3 Days 13 Hours 1 Minute 52 Seconds
当 TimeSpan
小于 1
秒时,我显示 Milliseconds
属性。这个代码很简单,但正如我上面所说的那样非常冗长。有没有一种类似于DateTime.Now.ToString("ddMMyyyy hhmmssffff")
的简洁方法来实现这一点?以下是我当前的代码:
public static string GetLongTime(TimeSpan t) {
string result = string.Empty;
if (t.Days > 0) {
if (t.Days == 1) result = "1 Day";
else result = $"{t.Days} Days";
} else if (t.TotalMilliseconds < 1000) {
if (t.Milliseconds > 0)
result = $"{t.Milliseconds}ms";
} else {
if (t.Hours > 0) {
if (t.Hours == 1) result += "1 Hour ";
else result += $"{t.Hours} Hours ";
}
if (t.Minutes > 0) {
if (t.Minutes == 1) result += "1 Minute ";
else result += $"{t.Minutes} Minutes ";
}
if (t.Seconds > 0) {
if (t.Seconds == 1) result += "1 Second ";
else result += $"{t.Seconds } Seconds ";
}
}
return result;
}
就像 DateTime
一样,TimeSpan
对象有一个 custom format list;然而,他们的示例列表显示带有良好 ol' 时尚 (s)
附加物的字符串:
TimeSpan duration = new TimeSpan(1, 12, 23, 62);
Console.WriteLine("Time of Travel: {0:%d} day(s)", duration);
Console.WriteLine("Time of Travel: {0:dd\.hh\:mm\:ss} days", duration);
Time of Travel: 1 day(s)
Time of Travel: 01.12:24:02 days
这不是我真正想要的。我还在 Whosebug 上查看了一些相关的 posts,正如一位用户在评论中指出的那样,它们是很好的资源。总的来说,这些都不是我正在寻找的解决方案,因为我主要寄希望于一些非常简洁的东西,例如:
return t.ToString("d Day?s");
当然以上只是伪造的,实际上不会做更多的事情:
3 Day?s
一些相关的 post 承诺重构我的代码;例如,this post 推荐条件赋值运算符:
string result = string.Empty;
if (t.Days > 0)
return $"{t.Days} {(t.Days > 1 ? "Days " : "Day ")}";
else if (t.TotalMilliseconds < 1000) {
if (t.Milliseconds > 0)
return $"{t.Milliseconds}ms";
} else {
if (t.Hours > 0)
result += $"{t.Hours} {(t.Hours > 1 ? "Hours " : "Hour ")}";
if (t.Minutes > 0)
result += $"{t.Minutes} {(t.Minutes > 1 ? "Minutes " : "Minute ")}";
if (t.Seconds > 0)
result += $"{t.Seconds} {(t.Seconds > 1 ? "Seconds " : "Second ")}";
}
return result;
虽然这缩短了代码,但它并没有使它看起来最干净(尤其是对于新开发人员而言)。这也符合 post 上的 this post that recommends using a SortedList
of the proper formats; however, I agree with the OP; 您的代码确实需要一些时间才能理解。这是我唯一不喜欢的东西。。
有没有办法在格式字符串中实现条件复数;或者,与我上面的方法相比,是否有更简单和简洁的方法?
.NET 中没有使这成为可能的内置 TimeSpan 格式说明符。
但是,我已经根据需要实现了此功能。它在我的免费开源 utility library 中可用。它是根据 MIT 许可发布的,因此您可以复制代码或将库包含在您的项目中。
用法(选择后一个选项时)
安装 NuGet 包。在程序包管理器控制台中键入以下内容:
Install-Package Karambolo.Common
然后您可以像这样使用 ToTimeReference 扩展方法转换 TimeSpan 值。
using System;
using Karambolo.Common;
using Karambolo.Common.Localization;
class Program
{
static void Main(string[] args)
{
var ts = new TimeSpan(3, 13, 1, 52);
Console.WriteLine(ts.ToTimeReference(4, "{0}", "now", "{0}", DefaultTextLocalizer.Instance));
}
}
上面的代码打印:
3 days 13 hours 1 minute 52 seconds
我在示例代码中使用的 ToTimeReference 重载使您可以完全控制输出的格式。最后一个参数是一个委托,负责指定时间间隔字符串的格式(如 "day"、"hour" 等)。它可用于本地化函数的输出。
这只是一个更短的方法。这里的可读性是一个视角问题:)
一些例子,看看是否符合要求。
TimeSpan ts = new TimeSpan(3, 4, 10, 25);
=> 3 Days 4 Hours 10 Minutes 25 Seconds
TimeSpan ts = new TimeSpan(0, 0, 0, 0, 700);
=> 700ms
TimeSpan ts = new TimeSpan(0, 2, 0, 1, 700);
=> 2 Hours 1 Second
TimeSpan ts = new TimeSpan(1, 1, 1, 1);
=> 1 Day 1 Hour 1 Minute 1 Second
TimeSpan ts = new TimeSpan([Some time span]);
string[] TFormat = new[] {
(ts.Days > 1 ? ts.Days + " Days" : (ts.Days == 1 ? "1 Day" : "")),
(ts.Hours > 1 ? " "+ ts.Hours + " Hours" : (ts.Hours == 1 ? " 1 Hour" : "")),
(ts.Minutes > 1 ? " " + ts.Minutes + " Minutes" : (ts.Minutes == 1 ? " 1 Minute" : "")),
(ts.Seconds > 1 ? " " + ts.Seconds + " Seconds" : (ts.Seconds == 1 ? " 1 Second" : "")),
(ts.TotalMilliseconds < 1000 ? $"{ts.TotalMilliseconds }ms" : "")
};
Console.WriteLine($"{TFormat[0]}{TFormat[1]}{TFormat[2]}{TFormat[3]}{TFormat[4]}".TrimStart());