C# 如何将时间 [ms, s, m, h, d] 作为字符串转换为秒作为整数



我想知道是否有一种快速方法(也许使用 TimeSpan(将持续时间时间格式的字符串(如17.24s20.79m1.3h(转换为秒格式,如17表示17.24s1260用于20.79m4699用于1.3h

感谢您的建议。

让我们从数学开始:

20.79 minutes == 20.79 * 60 seconds == 1247 seconds
1.3 hours   == 1.3 * 3600 seconds == 4680 seconds

我看不到12604699,这就是为什么我会坚持简单的数学,如果你坚持不同的逻辑,我会用\TODO:标记应该修改的代码。

对于不同的后缀,让我们提取模型:

private static Dictionary<string, Func<double, TimeSpan>> s_Builders =
new Dictionary<string, Func<double, TimeSpan>>(StringComparer.OrdinalIgnoreCase) {

{  "", x => TimeSpan.FromSeconds(x)},
{ "s", x => TimeSpan.FromSeconds(x)},
//TODO: if you insist on 1260, put required logic here
{ "m", x => TimeSpan.FromMinutes(x)},
//TODO: if you insist on 4699, put required logic here
{ "h", x => TimeSpan.FromHours(x)},
{ "d", x => TimeSpan.FromDays(x)},
}; 

实现TryMyParse方法的时间:

public static bool TryMyParse(string value, out TimeSpan result) {
result = default;
if (string.IsNullOrWhiteSpace(value))
return false;
string suffix = s_Builders
.Keys
.OrderByDescending(key => key.Length)
.FirstOrDefault(key => value.EndsWith(key, StringComparison.OrdinalIgnoreCase));
if (null == suffix)
return false;
else if (double.TryParse(value.Substring(0, value.Length - suffix.Length), 
out double number)) {
try {
result = s_Builders[suffix](number);
return true;
}
catch (OverflowException) {
return false;
}
catch (ArgumentException) {
return false;
}
}
return false;
}

最后,MyParse非常简单:

public static TimeSpan MyParse(string value) =>
TryMyParse(value, out var result)
? result
: throw new FormatException($"{value} is not a valid time");

演示:

string[] tests = new string[] {
"17.24s",
"20.79m", 
"1.3h",
};
string demo = string.Join(Environment.NewLine, tests
.Select(test => $"{test,6} :: {Math.Round(MyParse(test).TotalSeconds),4}"));
Console.Write(demo);

结果:

17.24s ::   17
20.79m :: 1247
1.3h :: 4680

Timespan确实有一个接受字符串参数的Parse方法,但它使用的输入格式与您想要的输入格式不同。在此处查看更多信息:https://learn.microsoft.com/en-us/dotnet/api/system.timespan.parse?view=netcore-3.1

您必须创建自己的 parse 方法来将字符串输入转换为Timespan,并使用TotalSeconds属性获取秒数。

如果你走这条路,我建议首先编写一个单元测试,其中包含所有被认为是有效的输入及其预期结果。从那里,您可以实现解析方法并进行验证。

namespace StackOverflow
{
public class Tests
{
[Fact]
public void TestTimespanStringConversion()
{
// Test cases go here...
Assert.Equal(TimeSpan.FromHours(1.2), "1.20h".AsTimeSpan())
}
}
public static class StringExtensions
{
public static TimeSpan AsTimeSpan(this string input)
{
// Conversion logic goes here...
return new TimeSpan();
}
}
}

谢谢大家的建议!我非常感激。这是我适合我的解决方案:

private int timeParser(string pTime) {
int iResult = 0;
double dTime = 0.0;
NumberStyles style = NumberStyles.Number;
CultureInfo culture = CultureInfo.InvariantCulture;

if(pTime.Contains("ms")) {
if(Double.TryParse(pTime.Trim().Replace("ms", ""), style, culture, out dTime)) {
iResult = (int)Math.Round(TimeSpan.FromMilliseconds(dTime).TotalSeconds);
} else {
throw new FormatException("Unable to convert " + pTime);
}
} else if(pTime.Contains("s")) {
if(Double.TryParse(pTime.Trim().Replace("s", ""), style, culture, out dTime)) {
iResult = (int)Math.Round(TimeSpan.FromSeconds(dTime).TotalSeconds);
} else {
throw new FormatException("Unable to convert " + pTime);
}                   
} else if(pTime.Contains("m")) {
if(Double.TryParse(pTime.Trim().Replace("m", ""), style, culture, out dTime)) {
iResult = (int)Math.Round(TimeSpan.FromMinutes(dTime).TotalSeconds);
} else {
throw new FormatException("Unable to convert " + pTime);
}
} else if(pTime.Contains("h")) {
if(Double.TryParse(pTime.Trim().Replace("h", ""), style, culture, out dTime)) {
iResult = (int)Math.Round(TimeSpan.FromHours(dTime).TotalSeconds);
} else {
throw new FormatException("Unable to convert " + pTime);
}
} else if(pTime.Contains("d")) {
if(Double.TryParse(pTime.Trim().Replace("d", ""), style, culture, out dTime)) {
iResult = (int)Math.Round(TimeSpan.FromDays(dTime).TotalSeconds);
} else {
throw new FormatException("Unable to convert " + pTime);
}
} else {
throw new FormatException(pTime + " is not a valid timeformat");
}
return iResult;
}

最新更新