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

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

duration*5

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

duration+duration+duration+duration+duration

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

【问题讨论】:

    标签: c# .net date time timespan


    【解决方案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】:
          【解决方案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 并不是真正的合成成员。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-05-27
            • 2021-05-22
            • 2018-11-13
            相关资源
            最近更新 更多