.NET 中的數字格式化,日期格式化

.NET 中的數字格式化,日期格式化

關鍵詞格式化,字符串,                                          

 

格式

基本內容是:可以在 Console.WriteLine(以及 String.Format,它被 Console.WriteLine 調用)中的格式字符串內的括號中放入非索引數字的內容。格式規範的完整形式如下:

{index [, width][:formatstring]}

其中,index 是此格式程序引用的格式字符串之後的參數,從零開始計數;width(如果有的話)是要設置格式的字段的寬度(以空格計)。width 取正數表示結果右對齊,取負數則意味着數字在字段中左對齊。(請參閱下面的前兩個示例。)

formatstring 是可選項,其中包含有關設置類型格式的格式說明。如果對象實現 IFormattableformatstring 就會傳遞給對象的 Format 方法(在 Beta 2 和後續版本中,該方法的簽名變爲 ToString(string, IFormatProvider),但功能不變)。如果對象不實現 IFormattable,就會調用 Object.ToString(),而忽略 formatstring

另請注意,在 Beta 1 中不區分當前語言的 ToString 在 Beta 2 和後續版本中“將”區分語言。例如,對於用“.”分隔千位,用“,”分隔小數的國家,1,234.56 將會格式化成 1.234,56。如果您需要結果無論在什麼語言下都是一樣的,就請使用 CultureInfo.InvariantCulture 作爲語言。

若要獲取有關格式的完整信息,請查閱“.NET 框架開發人員指南”中的格式概述(英文)

數字格式

請注意,數字的格式是區分語言的:分隔符以及分隔符之間的空格,還有貨幣符號,都是由語言決定的 — 默認情況下,是您計算機上的默認語言。默認語言與執行線程相關,可以通過 Thread.CurrentThread.CurrentCulture 瞭解和設置語言。有幾種方法,可以不必僅爲一種給定的格式操作就立即更改語言。

內置類型的字母格式

有一種格式命令以單個字母開頭,表示下列設置:

G—常規,E 或 F 中較短的

F—浮點數,常規表示法

E—用 E 表示法表示的浮點數(其中,E 代表 10 的次冪)

N—帶有分隔符的浮點數(在美國爲逗號)

C—貨幣,帶有貨幣符號和分隔符(在美國爲逗號)

D—十進制數,僅用於整型

X—十六進制數,僅用於整型

字母可以後跟一個數字,根據字母的不同,該數字可以表示總位數、有效位數或小數點後面的位數。

下面是字母格式的一些示例:

double pi = Math.PI;
double p0 = pi * 10000;
int i = 123;

Console.WriteLine("浮點格式,無分隔符(逗號)");
Console.WriteLine("pi, Left {0, -25}",   pi); // 3.1415926535897931
Console.WriteLine("p0, Rt.  {0, 25}",    p0); //        3.1415926535897931
Console.WriteLine("pi, E    {0, 25:E}",  pi); //               3.1416E+000

Console.WriteLine("使用 E 和 F 格式,小數點後保留 n(此處爲 4)位");
Console.WriteLine("pi, E4   {0, 25:E4}", pi); //               3.1416E+000
Console.WriteLine("pi, F4   {0, 25:F4}", pi); //                    3.1416 
Console.WriteLine("使用 G 格式,保留 4 位有效數字——如果需要請使用 E 格式");
Console.WriteLine("pi, G4   {0, 25:G4}", pi); //                     3.142
Console.WriteLine("p0, G4   {0, 25:G4}", p0); //                   3.142E4 

Console.WriteLine("N 和 C 格式帶有逗號(分隔符)," +
         "默認小數點後保留兩位,四捨五入。");
Console.WriteLine("p0, N    {0, 25:N}",  p0); //                 31,415.93 
Console.WriteLine("p0, N4   {0, 25:N4}", p0); //               31,415.9265 
Console.WriteLine("p0, C    {0,25:C}",   pi); //                     $3.14

Console.WriteLine("D 和 X 格式僅用於整型," +
         "非整型將產生格式異常——X 指十六進制");
Console.WriteLine("i,  D    {0, 25:D}",  i ); //                       123
Console.WriteLine("i,  D7   {0, 25:D7}", i ); //                   0000123
Console.WriteLine("i,  X    {0, 25:X}",  i ); //                        7B
Console.WriteLine("i,  X8   {0, 25:X8}", i ); //                  0000007B

圖片格式

與字母格式不同,formatstring 可以包含“圖片格式”。下面是從代碼中摘錄的幾個實例。(這類似於 Basic 中的“Print Using”語句。)圖片格式功能甚至包括以不同方式設置負數、正數和零的格式的能力。還有幾個圖片格式功能,下面的示例中未包括在內。有關詳細信息,請參閱“.NET 框架開發人員指南”或文檔中的主題圖片格式數字串(英文)

在下例中您將注意到,好心的博士既使用了“#”字符,又使用了“0”字符。如果相應的數字是前導零或尾隨零,“#”字符就會替換爲空值。無論相應數字的值如何,“0”字符都會被替換爲零字符 — 因此,數字將會被零填補。句號(如果有的話)表示小數分隔符的位置。

那麼,爲什麼要同時使用這些字母,比如“###0.##”? 如果要設置格式的值恰好爲零,“#” 圖片字符就被替換爲“無”(連零字符也不是)。您可能“總是”希望在小數點的左邊至少有一個“0”,否則,如果值爲零,字段就沒有輸出。換言之,僅包含“#”字符,一個“0”也沒有的格式常被認爲是一個編程錯誤。

逗號有兩種用法:如果一個逗號或一組逗號緊跟在句號的左邊(或者沒有句號時在結尾),它們就會告訴格式化程序分隔 10 ** (3 * n) 所顯示的數字,其中,n 是逗號的個數。換言之,數字按千位、百萬位、十億位等分隔。

如果逗號的右側至少有一個“0”或“#”佔位符,它就會告訴格式化程序在各數位組之間放置適當的組分隔符字符(在美國爲逗號。)(在美國,每三個數位算一組。)

可以設置百分比的格式,方法是在圖片中放入“%”。“%”將在指定的位置顯示,在顯示前數字將被乘以 100(這樣,0.28 就變成了 28%)。

如果希望將圖片格式用於指數表示法,可以指定“e”或“E”後跟加號或減號,再後跟任意個零,比如“E+00”或“e-000”。如果使用“e”,則顯示小寫“e” 。如果使用“E”,則顯示大寫“E” 。如果使用加號,則指數的符號總是出現。如果使用減號,則符號只有在指數爲負數時纔會顯示。(Beta 1 版在處理“-”時有問題,該符號會導致負號總是出現。)

根據要設置格式的數字的符號,還有一個條件格式。在格式字符串中僅包含兩個或三個獨立的格式,它們由分號分隔。如果有兩個格式,則第一個將用於非負數,第二個用於負數。如果有三個格式,則第一個將用於正數,第二個用於負數,第三個用於零。

可以在格式字符串中包含文字字符。如果所需的字符具有特殊意義,請在其前面使用反斜槓符號,使其“轉義”。例如,如果希望在不乘以 100 的情況下顯示百分比符號,就可以在數字前面使用反斜槓(在 C++ 和 C# 中必須使用兩個反斜槓),比如“#0.##//%”。(如果正在使用 C#,就可以使用極酷的逐字字符串文字,比如@"#0.##/%"。)或者,也可以將字符串放入單引號或雙引號中,以避免將其字符解釋爲格式命令。在 Beta 2 及更高版本中,可以通過使用雙括號,從而在格式字符串中包含文字括號。

下面是有關圖片格式的一些示例:

long m34 = 34000000; // 34,000,000
Console.WriteLine("幾種圖片格式");
Console.WriteLine("如果沒有數位,0 將打印 0;" +
         "諸如 i: 的文字總是打印");
Console.WriteLine("/t句點代表小數分隔符的位置");
Console.WriteLine("i,  i: 0000.0 {0, 10:i: 0000.0}", i); //    
i:0123.0
Console.WriteLine("如果沒有有效數字 # 將不顯示," +
         "逗號意味着放入分隔符");
Console.WriteLine("請確保在數字圖片中至少使用一個 0。");
Console.WriteLine("p0, ##,##0.#  {0, 10:##,##0.#}",-p0); //   -31,415.9
Console.WriteLine("m34, 0,,      {0, 10:0,, 百萬}", m34); // 34 百萬
Console.WriteLine("p0, #0.#E+00  {0, 10:#0.#E+00}", p0); //    31.4E+03
Console.WriteLine("% 乘以 100 並打印百分號");
Console.WriteLine("pi, ###0.##%  {0, 10:###0.##%}", pi); //     314.16%
Console.WriteLine("因爲 // 而沒有進行乘法運算" +
"(注意:兩個反斜線!)");
Console.WriteLine("pi, ###0.##////% {0, 10:###0.##//%}", pi); //  3.14%
Console.WriteLine("與 C# 的逐字字符串相同");
Console.WriteLine(@"pi, ###0.##//% {0, 10:###0.##/%}", pi); //    3.14%
Console.WriteLine("10, '#'#0     {0, 10:'#'#0}",      10); //       #10
Console.WriteLine("基於符號的條件格式");
Console.WriteLine("如果是 0 或正數打印 #,如果是負數打印 (#)");
Console.WriteLine("-5  0;(0)     {0, 10:0;(0)}",    -5); //         (5)
Console.WriteLine("如果是正數打印 #,如果是負數打印 -#,如果是 0 打印 zip");
Console.WriteLine(" 0  0;-0;zip  {0, 10:0;-0;zip}",  0); //         zip

如您所見,格式功能非常強大。

格式的工作方式

文檔中的示例對所傳遞的對象類型的變量調用 Format 方法。對這些 Format 方法僅傳遞格式規範的 formatstring 部分,而不傳遞 indexwidth。(在 Beta 2 中,對 Format 的調用將改爲對 ToString 的調用。)

indexwidthString.Format(它被 Console.WriteConsole.WriteLine 調用)使用,以獲得調用 Format 的正確對象以及將該調用的結果左或右對齊。(順便說一下,如果要設置格式的對象不實現 IFormattable(並因此調用 Format 方法),String.Format 將調用對象的 ToString() 方法,而忽略 formatstring。)

換言之,Console.WriteLine 調用 String.Format,傳遞向它傳遞的所有參數。String.Format 分析字符串,查找“{”字符。找到該字符後,它將分析子字符串直到第一個“}”爲止,以確定 index 數、widthformatstring。然後,它按照 index 訪問相應的參數,並調用其 Format 方法,傳遞“{}”段中的 formatstring 部分。(如果參數對象不實現 IFormattable,則被調用的是 ToString。)

無論是實現還是不實現,都會返回一個字符串,並且 String.Format 在繼續分析格式字符串之前會將其與結果字符串連接。之後,String.Format 將生成的帶格式字符串返回給 Console.WriteLine,由 Console.WriteLine 進行顯示。

對於 Beta 2 及更高版本,對象的 Format 方法(它是 IFormattable 中的 Format 方法)被 ToString 所替代,ToString 獲取一個格式字符串和一個 IFormatProvider(或 null)。但 String.Format 仍存在,因此這些調用將不改變。

自定義格式

您自己也可以編寫格式化程序,用於自己的類型或作爲內置類型的自定義格式化程序,如“.NET 框架開發人員指南”中的自定義 Format 方法所說明的那樣。如果編寫內置類型的自定義格式化程序,就不能從 Console.WriteLine 中使用它,但可以通過調用 String.Format 的重載而使用它,String.Format 的重載將採用 IServiceObjectProvider(在 beta 2 及更高版本中稱爲 IFormatProvider)作爲參數。

日期和時間格式

您將記起,有一個叫做 DateTime 的類,用於保存日期和時間。像您所猜想的那樣,有大量方法可供設置 DateTime 對象的格式:僅日期、僅時間、世界時或本地時、若干種日/月/年順序,甚至可分類。日期和時間格式是區分語言的。

還可以使用自定義格式字符串來設置 DateTime 對象的格式。這種字符串將包含由某些字母組成的區分大小寫的子字符串,以表示日期和時間的各個不同部分,如星期幾、幾號、月份、年份、紀元、小時、分鐘、秒或時區。這些部分中有許多具有多種格式,例如,M 是沒有前導零的數字月份,MM 是有前導零的數字月份,MMM 是三個字母的月份縮寫,MMMM 是所在國家語言對應的完整月份名稱的拼寫。在“.NET 框架參考”中可以找到自定義和標準格式字符的完整列表

下面是有關日期和時間格式的一個示例:

Console.WriteLine("標準格式");
// 後面的“分析”中會有更多信息
DateTime dt = DateTime.Parse("2001 年 1 月 1 日,12:01:00am"); 
Console.WriteLine("d:   {0:d}", dt); // 1/1/2001
Console.WriteLine("D:   {0:D}", dt); // 2001 年 1 月 1 日,星期一
Console.WriteLine("f:   {0:f}", dt); // 2001 年 1 月 1 日,星期一 12:01 AM
Console.Write("F:   {0:F}", dt); // 2001 年 1 月 1 日,星期一 12:01:00 AM
Console.WriteLine();
Console.WriteLine("g:   {0:g}", dt); // 1/1/2001 12:01 AM
Console.WriteLine("G:   {0:G}", dt); // 1/1/2001 12:01:00 AM
Console.WriteLine("M/m: {0:M}", dt); // 2001 年 1 月 
Console.WriteLine("R/r: {0:R}", dt); // 2001 年 1 月 1 日,星期一 08:01:00 GMT
Console.WriteLine("s:   {0:s}", dt); // 2001-01-01T00:01:00
Console.WriteLine("t:   {0:t}", dt); // 12:01 AM
Console.WriteLine("T:   {0:T}", dt); // 12:01:00 AM
Console.WriteLine("u:   {0:u}", dt); // 2001-01-01 08:01:00Z
Console.Write("U:   {0:U}", dt); // 2001 年 1 月 1 日,星期一 8:01:00 AM
Console.WriteLine();
Console.WriteLine("Y/y: {0:Y}", dt); // 2001 年 1 月
Console.WriteLine("自定義格式");
// 對作爲格式使用的字符必須“轉義”—此處爲 t 和 z
// 同時使用引號(在文字字符串中)和反斜槓
Console.WriteLine(@"dddd, dd MMMM yyyy"" at ""HH:mm:ss in /zone zzz:");
Console.WriteLine(@"{0:dddd, dd MMMM yyyy"" at ""HH:mm:ss in /zone zzz}",
      dt);
   //    2001 年 1 月 1 日,星期一  00:01:00 於時區 -08:00
http://www.microsoft.com/china/MSDN/library/archives/library/welcome/dsmsdn/drguinet03292001.asp
程序:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
 class Program
 {
  static void Main(string[] args)
  {
   double pi = Math.PI;
   double p0 = pi * 10000;
   int i = 123;
   long m34 = 34000000; // 34,000,000
   Console.WriteLine("幾種圖片格式");
   Console.WriteLine("如果沒有數位,0 將打印 0;" +
      "諸如 i: 的文字總是打印");
   Console.WriteLine("/t句點代表小數分隔符的位置");
   Console.WriteLine("i,  i: 0000.0 {0, 10:i: 0000.0}", i); //    i:0123.0
   Console.WriteLine("如果沒有有效數字 # 將不顯示," +
      "逗號意味着放入分隔符");
   Console.WriteLine("請確保在數字圖片中至少使用一個 0。");
   Console.WriteLine("p0, ##,##0.#  {0, 10:##,##0.#}", -p0); //   -31,415.9
   Console.WriteLine("m34, 0,,      {0, 10:0,, 百萬}", m34); // 34 百萬
   Console.WriteLine("p0, #0.#E+00  {0, 10:#0.#E+00}", p0); //    31.4E+03
   Console.WriteLine("% 乘以 100 並打印百分號");
   Console.WriteLine("pi, ###0.##%  {0, 10:###0.##%}", pi); //     314.16%
   Console.WriteLine("pi, ###0.##%  {0, 10:#######0.##%}", pi); //     314.16%
   Console.WriteLine("因爲 // 而沒有進行乘法運算" +
   "(注意:兩個反斜線!)");
   Console.WriteLine("pi, ###0.##////% {0, 10:###0.##//%}", pi); //  3.14%
   Console.WriteLine("與 C# 的逐字字符串相同");
   Console.WriteLine(@"pi, ###0.##//% {0, 10:###0.##/%}", pi); //    3.14%
   Console.WriteLine("10, '#'#0     {0, 10:'#'#0}", 10); //       #10
   Console.WriteLine("10, '#'#0     {0, 10:##0}", 10); //       10
   Console.WriteLine("基於符號的條件格式");
   Console.WriteLine("如果是 0 或正數打印 #,如果是負數打印 (#)");
   Console.WriteLine("-5  0;(0)     {0, 10:0;(0)}", -5); //         (5)
   Console.WriteLine("如果是正數打印 #,如果是負數打印 -#,如果是 0 打印 zip");
   Console.WriteLine(" 0  0;-0;zip  {0, 10:0;-0;zip}", 0); //         zip
   Console.ReadLine();
  }
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章