在 .NET 中乘以时间跨度

Posted

技术标签:

【中文标题】在 .NET 中乘以时间跨度【英文标题】:Multiply TimeSpan in .NET 【发布时间】:2012-04-12 03:19:06 【问题描述】:

如何在 C# 中乘以 TimeSpan 对象?假设变量duration是TimeSpan,我想,例如

duration*5

但这给了我一个错误“运算符 * 不能应用于类型 TimeSpan 和 int”。这是我目前的解决方法

duration+duration+duration+duration+duration

但这不会扩展到非整数倍数,例如。 duration * 3.5

【问题讨论】:

【参考方案1】:

乘法现在可用于 TimeSpan!!!

但仅适用于 .NET Core.NET Standard.NET 5+。

.NET Core 2.0(或.NET Standard 2.1)您可以成功运行以下代码:

Console.WriteLine(TimeSpan.FromSeconds(45) * 3);
// Prints:
// 00:02:15

限制

不过,请务必注意 (as described in the docu),这仅适用于 .NET Core 2.0+、.NET Standard 2.1+,当然还有 .NET 5+。

即使在最新的 .NET Framework 版本中,上面的代码也会失败:4.8(实际上是 的最后一个版本.NET 框架!)。

如果您在 Console 应用程序中尝试上述代码,例如,运行 .NET Core 1.1 或更低版本,或者 .NET Framework 4.8 或更低会抛出以下异常:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Operator '*' 不能应用于'System.TimeSpan' 和'int''类型的操作数


为什么不在 .NET Framework 中?

为了尝试理解为什么某些功能会添加到.Net Core而不是.NET Framework,看到what Immo says很有启发性:

.NET Core 是 .NET 的开源、跨平台和快速发展版本。由于它的并行特性,它可以进行我们不能冒险应用回 .NET Framework 的更改。这意味着 .NET Core 将随着时间的推移获得 .NET Framework 无法获得的新 API 和语言功能。在 Build 中,我们演示了文件 API 如何在 .NET Core 上更快。如果我们将这些相同的更改放入 .NET Framework 中,我们可能会破坏现有的应用程序,而我们不想这样做。

【讨论】:

Immo 的引用与向TimeSpan 类型添加新运算符完全无关。它不能破坏任何现有的代码,因为没有旧的实现。也许存在代码许可问题,但没有技术原因 .NET Framework 也不能进行此更改。【参考方案2】:

TimeSpan.Multiply 已抵达 .NET Core,看起来它将抵达 .NET Standard 2.1:

https://docs.microsoft.com/en-us/dotnet/api/system.timespan.op_multiply?view=netstandard-2.1

   var result = 3.0 * TimeSpan.FromSeconds(3);

【讨论】:

【参考方案3】:

对于那些希望复制和粘贴的人:

namespace Utility

    public static class TimeSpanExtension
    
        /// <summary>
        /// Multiplies a timespan by an integer value
        /// </summary>
        public static TimeSpan Multiply(this TimeSpan multiplicand, int multiplier)
        
            return TimeSpan.FromTicks(multiplicand.Ticks * multiplier);
        

        /// <summary>
        /// Multiplies a timespan by a double value
        /// </summary>
        public static TimeSpan Multiply(this TimeSpan multiplicand, double multiplier)
        
            return TimeSpan.FromTicks((long)(multiplicand.Ticks * multiplier));
        
    

示例用法:

using Utility;

private static void Example()

    TimeSpan t = TimeSpan.FromSeconds(30).Multiply(5);

t 将结束为 150 秒。

【讨论】:

扩展方法是解决这类问题最方便的方法。 multiplier 参数可以是 long 类型,无需额外费用。 如果它对任何人有用,我选择添加溢出检查,抛出 if long.MaxValue / multiplier multiplicand.Ticks,用于 int 乘数。由于通过将双倍转换为长在后楼层中实现,因此相同的逻辑应该适用于双倍乘数。【参考方案4】:

这里的问题是你想乘以时间跨度。最简单的解决方法是使用刻度。例如。

 var ticks = TimeSpan.FromMinutes(1).Ticks;
 var newTimeSpan = TimeSpan.FromTicks(ticks*5);

【讨论】:

【参考方案5】:

可以使用TimeSpan的内部数据,即tick。

TimeSpan day = TimeSpan.FromDays(1);
TimeSpan week = TimeSpan.FromTicks(day.Ticks * 7);

【讨论】:

【参考方案6】:

From this article

TimeSpan duration = TimeSpan.FromMinutes(1);
duration = TimeSpan.FromTicks(duration.Ticks * 12);
Console.WriteLine(duration);     

【讨论】:

谢谢我用TimeSpan.FromTicks((long)(duration.Ticks*multiplier)) 我宁愿使用扩展方法。就像 Stephen Hewlett 在他对这个问题的回答中所建议的那样。 @MikedeKlerk 同意,但这更像是语法糖。 OP 仍然需要知道答案的根源,以便它可以应用于任何方法、扩展与否【参考方案7】:

使用记号:

http://www.personal.psu.edu/wbk2/blogs/personal_blog/dotnet-stuff-timespan-multiplication-and-division.html

【讨论】:

【参考方案8】:

TimeSpan 结构不为* 运算符提供重载,因此您必须自己执行此操作:

var result = TimeSpan.FromTicks(duration.Ticks * 5);

【讨论】:

【参考方案9】:

您需要指定要乘以 5 的成员 -> TimeSpan.TotalMinutes * 5

【讨论】:

这确实有效 - 但更好的通用解决方案是将刻度乘以恕我直言。 不,TimeSpan 是一个标量。 T * 5 也应该乘以小时和秒。 @HenkHolterman 但TotalMinutes 是以分钟表示的时间跨度的总持续时间,因此如果时间跨度表示一小时零十分三十秒,TotalMinutes 将返回 70.5。 @HenkHolterman 正如 phoog 所指出的,TotalMinutes 属性是一个 Double,它给出了整个 TimeSpan 的总分钟数,同时考虑了所有其他字段。尽管Ticks 看起来确实是一种更好的方法,但此解决方案的工作原理相同。但请注意,如果您想向用户展示一些有意义的信息,那么稍后需要将 Ticks 转换为分钟。 同意,我对句子的第一部分做出了反应。 TotalMinutes 并不是真正的合成成员。

以上是关于在 .NET 中乘以时间跨度的主要内容,如果未能解决你的问题,请参考以下文章

需要将时间跨度 ADO.NET 数据列格式化为 AM/PM

使用asp.net计算时间跨度[重复]

TCP 错误代码 10061:无法连接到 net.tcp://。连接尝试持续了 00:00:01.0156241 的时间跨度

与图像的重叠跨度

如何选择表格中的最后一个行跨度?

如何破译哨兵警告; “连接类型的跨度与操作 id (null)..”