Dot-Net

你能捨入一個 .NET TimeSpan 對象嗎?

  • December 3, 2008

你能捨入一個 .NETTimeSpan對象嗎?

我的Timespan值為:00:00:00.6193789

有沒有一種簡單的方法可以將其保留為TimeSpan對象但將其舍入到

00:00:00.62 之類的東西?

對不起,伙計們,但到目前為止的問題和流行的答案都是錯誤的***:-)***

這個問題是錯誤的,因為 Tyndall 要求一種入方法,但顯示了一個截斷範例。

Will Dean 的回答是錯誤的,因為它還解決了truncation而不是rounding。(我想人們可能會爭辯說,這兩個問題之一的答案是正確的,但讓我們暫時把哲學放在一邊……)

這是一個簡單的捨入技術:

int precision = 2; // Specify how many digits past the decimal point
TimeSpan t1 = new TimeSpan(19365678); // sample input value

const int TIMESPAN_SIZE = 7; // it always has seven digits
// convert the digitsToShow into a rounding/truncating mask
int factor = (int)Math.Pow(10,(TIMESPAN_SIZE - precision));

Console.WriteLine("Input: " + t1);
TimeSpan truncatedTimeSpan = new TimeSpan(t1.Ticks - (t1.Ticks % factor));
Console.WriteLine("Truncated: " + truncatedTimeSpan);
TimeSpan roundedTimeSpan =
   new TimeSpan(((long)Math.Round((1.0*t1.Ticks/factor))*factor));
Console.WriteLine("Rounded: " + roundedTimeSpan);

使用範常式式碼中的輸入值和位數,這是輸出:

Input: 00:00:01.9365678
Truncated: 00:00:01.9300000
Rounded: 00:00:01.9400000

將精度從 2 位更改為 5 位,然後改為:

Input: 00:00:01.9365678
Truncated: 00:00:01.9365600
Rounded: 00:00:01.9365700

甚至將其更改為 0 以獲得此結果:

Input: 00:00:01.9365678
Truncated: 00:00:01
Rounded: 00:00:02

最後,如果您只想對輸出進行更多控制,請添加一些格式。這是一個範例,表明您可以將精度與顯示的位數分開。精度再次設置為 2,但顯示 3 位數字,如格式化控製字元串的最後一個參數中所指定:

Console.WriteLine("Rounded/formatted: " + 
 string.Format("{0:00}:{1:00}:{2:00}.{3:000}",
     roundedTimeSpan.Hours, roundedTimeSpan.Minutes,
     roundedTimeSpan.Seconds, roundedTimeSpan.Milliseconds));
// Input: 00:00:01.9365678
// Truncated: 00:00:01.9300000
// Rounded: 00:00:01.9400000
// Rounded/formatted: 00:00:01.940

2010.01.06 更新:開箱即用的解決方案

如果您正在尋找想法,上述材料很有用;從那以後,我有時間為那些尋找即用型程式碼的人實施一個打包的解決方案。

請注意,這是未註釋的程式碼。帶有 XML-doc-comments 的完整註釋版本將在本季度末在我的開源庫中提供。儘管我猶豫是否要像這樣“原始”地發布它,但我認為它仍然對感興趣的讀者有所幫助。

這段程式碼改進了我上面的程式碼,雖然它是四捨五入的,但仍然顯示了 7 個位置,用零填充。這個完成的版本四捨五入並修剪到指定的位數。

這是一個範例呼叫:

Console.Write(new RoundedTimeSpan(19365678, 2).ToString());
// Result = 00:00:01.94

這是完整的 RoundedTimeSpan.cs 文件:

using System;

namespace CleanCode.Data
{
   public struct RoundedTimeSpan
   {

       private const int TIMESPAN_SIZE = 7; // it always has seven digits

       private TimeSpan roundedTimeSpan;
       private int precision;

       public RoundedTimeSpan(long ticks, int precision)
       {
           if (precision < 0) { throw new ArgumentException("precision must be non-negative"); }
           this.precision = precision;
           int factor = (int)System.Math.Pow(10, (TIMESPAN_SIZE - precision));

           // This is only valid for rounding milliseconds-will *not* work on secs/mins/hrs!
           roundedTimeSpan = new TimeSpan(((long)System.Math.Round((1.0 * ticks / factor)) * factor));
       }

       public TimeSpan TimeSpan { get { return roundedTimeSpan; } }

       public override string ToString()
       {
           return ToString(precision);
       }

       public string ToString(int length)
       { // this method revised 2010.01.31
           int digitsToStrip = TIMESPAN_SIZE - length;
           string s = roundedTimeSpan.ToString();
           if (!s.Contains(".") && length == 0) { return s; }
           if (!s.Contains(".")) { s += "." + new string('0', TIMESPAN_SIZE); }
           int subLength = s.Length - digitsToStrip;
           return subLength < 0 ? "" : subLength > s.Length ? s : s.Substring(0, subLength);
       }
   }
}

2010.02.01 更新:打包解決方案現已推出

我昨天剛剛發布了我的開源庫的新版本,比預期的要早,包括我上面描述的 RoundedTimeSpan。程式碼在這裡;對於 API 從此處開始,然後導航到命名空間RoundedTimeSpanCleanCode.Data。CleanCode.DLL 庫包括上面顯示的程式碼,但在完成的包中提供了它。請注意,ToString(int)自從我在 2010.01.06 發布後,我對上述方法進行了輕微改進。

引用自:https://stackoverflow.com/questions/338658