C#如何将时间[ms,s,m,h,d]转换为字符串形式的秒数转换为int形式的秒数

C#如何将时间[ms,s,m,h,d]转换为字符串形式的秒数转换为int形式的秒数,c#,timespan,C#,Timespan,我想知道是否有一种快速方法(可能是使用TimeSpan)将持续时间格式的字符串(如17.24s或20.79m或1.3h转换为秒格式,如17的17.24s,1260的20.79m和4699的1.3h 谢谢您的建议。Timespan确实有一个接受字符串参数的Parse方法,但它使用的输入格式与您想要的不同。请参见此处的更多信息: 您必须使用自己的解析方法将字符串输入转换为Timespan,并使用TotalSeconds属性获取秒数 如果你走这条路,我建议首先写一个单元测试,包含所有被认为有效的输入和

我想知道是否有一种快速方法(可能是使用TimeSpan)将持续时间格式的字符串(如
17.24s
20.79m
1.3h
转换为秒格式,如
17
17.24s
1260
20.79m
4699
1.3h


谢谢您的建议。

Timespan
确实有一个接受字符串参数的
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();
        }
    }
}

Timespan
确实有一个接受字符串参数的
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();
        }
    }
}
让我们从数学开始:

我看不到
1260
4699
,这就是我坚持简单数学的原因,我会用
\\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)},
}; 
最后,
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
结果:

  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
让我们从数学开始:

我看不到
1260
4699
,这就是我坚持简单数学的原因,我会用
\\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)},
}; 
最后,
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
结果:

  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

谢谢大家的建议!我非常感激。以下是我的解决方案:

    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;
    }

谢谢大家的建议!我非常感激。以下是我的解决方案:

    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;
    }


你能更好地解释在这个转变中要遵循的规则吗?例如,1.3h在什么逻辑下变为4699 in base?有类似于
TimeSpan的方法。可以使用FromHours/FromMinutes/FromSeconds
从数字中获取时间跨度,然后访问
TotalSeconds
属性。e、 g.
TimeSpan.FromHours(1.3).TotalSeconds
返回4680(1.3*60*60)。因为它返回一个double,看起来您想要一个整数,所以您可以根据场景的需要进行舍入/强制转换。我的错@Dmitry Bychenko的回答是正确的:20.79分钟==20.79*60秒==1247秒1.3小时==1.3*3600秒==4680秒你能更好地解释这个转换要遵循的规则吗?例如,1.3h在什么逻辑下变为4699 in base?有类似于
TimeSpan的方法。可以使用FromHours/FromMinutes/FromSeconds
从数字中获取时间跨度,然后访问
TotalSeconds
属性。e、 g.
TimeSpan.FromHours(1.3).TotalSeconds
返回4680(1.3*60*60)。因为它返回一个double,看起来您想要一个整数,所以您可以根据场景的需要进行舍入/强制转换。我的错@Dmitry Bychenko的回答是正确的:20.79分钟==20.79*60秒==1247秒1.3小时==1.3*3600秒==4680秒就像你想比较的
“1.2h.AsTimeSpan()
时间跨度FromHours(1.2)
是的,我现在想起来应该是第一个,所以应该是
断言.Equal(时间跨度FromHours(1.2),“1.20h“.AsTimeSpan())
。编辑后的回答似乎您希望将
1.2h.AsTimeSpan()与
TimeSpan.FromHours(1.2)
进行比较。是的,我现在回想起来,预期是第一个,所以应该是
Assert.Equal(TimeSpan.FromHours(1.2),“1.20h.AsTimeSpan())
。编辑回答我首先将字符串解析为数字和后缀,然后使用后缀在字典中查找翻译方法,而不是在字典中迭代。请注意,
后缀
永远不会为
,因为所有字符串都以
结尾。”“
@juharr:为了安全起见,我检查了
null
:如果
{”“…
在模型中被注释掉,我们很可能会有
null
后缀。将字符串拆分为数字和后缀(如“1.23e-2y2e4”)不是一件容易的事(一般情况下)使用
1.23e-2
number和
y2e4
后缀;我承认这个例子是学术性的,但我想稳妥一点,我只检查最后一个字符是否是数字,因为我们只需要一个字符后缀。如果不是,那就是后缀。如果是一个数字,没有后缀,您尝试将整个字符串解析为双精度。现在如果我们需要处理不同长度的后缀,那么你所拥有的将更有意义。你是对的。20.79分钟==20.79*60秒==1247秒1.3小时==1.3*3600秒==4680秒我首先将字符串解析为数字和后缀,然后使用后缀在字典中查找翻译方法,而不是han在字典上迭代。请注意,
suffix
永远不会是
null
,因为所有字符串都以
结尾。
@juharr:我检查
null
是否安全:如果
{“”…
在模型中被注释掉,我们很可能会有
null
后缀。这不是那么容易的任务(一般情况下)将字符串拆分为数字和后缀