日期及数字格式化

时间:2023-02-26 19:27:50

本文转载自:http://www.csharpwin.com/csharpspace/7843r1361.shtml

 

字符串格式化这部分内容是我们经常用到的,如“2008-03-26”日期格式、“28.20”数字格式。

举一个例子,我们有时需要将订单号“12”显示为“00000012”这种样式(不足8位前面补0),就可以使用下面的方法:

  1. int originalCode=12;
  2. Response.Write(string.Format("{0:00000000}",originalCode));

或者

  1. int originalCode=12;
  2. Response.Write(originalCode.ToString("00000000"))

又如我们在使用日期做为某种关键字时,比如图片的文件名,一般是到秒级,如“20080326082708”

  1. Response.Write(DateTime.Now.ToString("yyyyMMddHHmmss"));//输出:20080326082708

这样如果并发操作比较多的话,就会产生文件重名的现象。我们可以将日期精确到1/10000000秒,这样的话重名的可能性就很小了。

  1. //输出:200803260827087983268
  2. Response.Write(DateTime.Now.ToString("yyyyMMddHHmmssfffffff"));

格式

基本内容是:可以在Console.WriteLine(以及String.Format,它被Console.WriteLine调用)中的格式字符串内的括号中放入非索引数字的内容。格式规范的完整形式如下:

  1. {index[,width][:formatstring]}

其中,index是此格式程序引用的格式字符串之后的参数,从零开始计数;width(如果有的话)是要设置格式的字段的宽度(以空格计)。width取正数表示结果右对齐,取负数则意味着数字在字段中左对齐。(请参阅下面的前两个示例。)

formatstring是可选项,其中包含有关设置类型格式的格式说明。如果对象实现IFormattable,formatstring就会传递给对象的Format方法(在Beta2和后续版本中,该方法的签名变为ToString(string,IFormatProvider),但功能不变)。如果对象不实现IFormattable,就会调用Object.ToString(),而忽略formatstring。

另请注意,在Beta1中不区分当前语言的ToString在Beta2和后续版本中“将”区分语言。例如,对于用“.”分隔千位,用“,”分隔小数的国家,1,234.56将会格式化成1.234,56。如果您需要结果无论在什么语言下都是一样的,就请使用CultureInfo.InvariantCulture作为语言。

若要获取有关格式的完整信息,请查阅“.NET框架开发人员指南”中的格式概述(英文)。

数字格式

请注意,数字的格式是区分语言的:分隔符以及分隔符之间的空格,还有货币符号,都是由语言决定的—默认情况下,是您计算机上的默认语言。默认语言与执行线程相关,可以通过Thread.CurrentThread.CurrentCulture了解和设置语言。有几种方法,可以不必仅为一种给定的格式操作就立即更改语言。

内置类型的字母格式

有一种格式命令以单个字母开头,表示下列设置:

G—常规,E或F中较短的

F—浮点数,常规表示法

E—用E表示法表示的浮点数(其中,E代表10的次幂)

N—带有分隔符的浮点数(在美国为逗号)

C—货币,带有货币符号和分隔符(在美国为逗号)

D—十进制数,仅用于整型

X—十六进制数,仅用于整型

字母可以后跟一个数字,根据字母的不同,该数字可以表示总位数、有效位数或小数点后面的位数。

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

  1. double pi=Math.PI;
  2. double p0=pi*10000;
  3. int i=123;
  4. Console.WriteLine("浮点格式,无分隔符(逗号)");
  5. Console.WriteLine("pi,Left{0,-25}",pi);//3.1415926535897931
  6. Console.WriteLine("p0,Rt.{0,25}",p0);//3.1415926535897931
  7. Console.WriteLine("pi,E{0,25:E}",pi);//3.1416E+000
  8. Console.WriteLine("使用E和F格式,小数点后保留n(此处为4)位");
  9. Console.WriteLine("pi,E4{0,25:E4}",pi);//3.1416E+000
  10. Console.WriteLine("pi,F4{0,25:F4}",pi);//3.1416
  11. Console.WriteLine("使用G格式,保留4位有效数字——如果需要请使用E格式");
  12. Console.WriteLine("pi,G4{0,25:G4}",pi);//3.142
  13. Console.WriteLine("p0,G4{0,25:G4}",p0);//3.142E4
  14. Console.WriteLine("N和C格式带有逗号(分隔符),"+
  15. "默认小数点后保留两位,四舍五入。");
  16. Console.WriteLine("p0,N{0,25:N}",p0);//31,415.93
  17. Console.WriteLine("p0,N4{0,25:N4}",p0);//31,415.9265
  18. Console.WriteLine("p0,C{0,25:C}",pi);// $3.14
  19. Console.WriteLine("D和X格式仅用于整型,"+
  20. "非整型将产生格式异常——X指十六进制");
  21. Console.WriteLine("i,D{0,25:D}",i);//123
  22. Console.WriteLine("i,D7{0,25:D7}",i);//0000123
  23. Console.WriteLine("i,X{0,25:X}",i);//7B
  24. Console.WriteLine("i,X8{0,25:X8}",i);//0000007B

图片格式

与字母格式不同,formatstring可以包含“图片格式”。下面是从代码中摘录的几个实例。(这类似于Basic中的“PrintUsing”语句。)图片格式功能甚至包括以不同方式设置负数、正数和零的格式的能力。还有几个图片格式功能,下面的示例中未包括在内。有关详细信息,请参阅“.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”。如果使用加号,则指数的符号总是出现。如果使用减号,则符号只有在指数为负数时才会显示。(Beta1版在处理“-”时有问题,该符号会导致负号总是出现。)

根据要设置格式的数字的符号,还有一个条件格式。在格式字符串中仅包含两个或三个独立的格式,它们由分号分隔。如果有两个格式,则第一个将用于非负数,第二个用于负数。如果有三个格式,则第一个将用于正数,第二个用于负数,第三个用于零。

可以在格式字符串中包含文字字符。如果所需的字符具有特殊意义,请在其前面使用反斜杠符号,使其“转义”。例如,如果希望在不乘以100的情况下显示百分比符号,就可以在数字前面使用反斜杠(在C++和C#中必须使用两个反斜杠),比如“#0.##\%”。(如果正在使用C#,就可以使用极酷的逐字字符串文字,比如@"#0.##%"。)或者,也可以将字符串放入单引号或双引号中,以避免将其字符解释为格式命令。在Beta2及更高版本中,可以通过使用双括号,从而在格式字符串中包含文字括号。

下面是有关图片格式的一些示例:

  1. long m34=34000000;//34,000,000
  2. Console.WriteLine("几种图片格式");
  3. Console.WriteLine("如果没有数位,0将打印0;"+
  4. "诸如i:的文字总是打印");
  5. Console.WriteLine("t句点代表小数分隔符的位置");
  6. Console.WriteLine("i,i:0000.0{0,10:i:0000.0}",i);//i:0123.0
  7. Console.WriteLine("如果没有有效数字#将不显示,"+
  8. "逗号意味着放入分隔符");
  9. Console.WriteLine("请确保在数字图片中至少使用一个0。");
  10. Console.WriteLine("p0,##,##0.#{0,10:##,##0.#}",-p0);//-31,415.9
  11. Console.WriteLine("m34,0,,{0,10:0,,百万}",m34);//34百万
  12. Console.WriteLine("p0,#0.#E+00{0,10:#0.#E+00}",p0);//31.4E+03
  13. Console.WriteLine("%乘以100并打印百分号");
  14. Console.WriteLine("pi,###0.##%{0,10:###0.##%}",pi);//314.16%
  15. Console.WriteLine("因为\而没有进行乘法运算"+
  16. "(注意:两个反斜线!)");
  17. Console.WriteLine("pi,###0.##\\%{0,10:###0.##\%}",pi);//3.14%
  18. Console.WriteLine("与C#的逐字字符串相同");
  19. Console.WriteLine(@"pi,###0.##\%{0,10:###0.##%}",pi);//3.14%
  20. Console.WriteLine("10,'#'#0{0,10:'#'#0}",10);//#10
  21. Console.WriteLine("基于符号的条件格式");
  22. Console.WriteLine("如果是0或正数打印#,如果是负数打印(#)");
  23. Console.WriteLine("-50;(0){0,10:0;(0)}",-5);//(5)
  24. Console.WriteLine("如果是正数打印#,如果是负数打印-#,如果是0打印zip");
  25. Console.WriteLine("00;-0;zip{0,10:0;-0;zip}",0);//zip

如您所见,格式功能非常强大。

格式的工作方式

文档中的示例对所传递的对象类型的变量调用Format方法。对这些Format方法仅传递格式规范的formatstring部分,而不传递index和width。(在Beta2中,对Format的调用将改为对ToString的调用。)

index和width由String.Format(它被Console.Write和Console.WriteLine调用)使用,以获得调用Format的正确对象以及将该调用的结果左或右对齐。(顺便说一下,如果要设置格式的对象不实现IFormattable(并因此调用Format方法),String.Format将调用对象的ToString()方法,而忽略formatstring。)

换言之,Console.WriteLine调用String.Format,传递向它传递的所有参数。String.Format分析字符串,查找“{”字符。找到该字符后,它将分析子字符串直到第一个“}”为止,以确定index数、width和formatstring。然后,它按照index访问相应的参数,并调用其Format方法,传递“{}”段中的formatstring部分。(如果参数对象不实现IFormattable,则被调用的是ToString。)

无论是实现还是不实现,都会返回一个字符串,并且String.Format在继续分析格式字符串之前会将其与结果字符串连接。之后,String.Format将生成的带格式字符串返回给Console.WriteLine,由Console.WriteLine进行显示。

对于Beta2及更高版本,对象的Format方法(它是IFormattable中的Format方法)被ToString所替代,ToString获取一个格式字符串和一个IFormatProvider(或null)。但String.Format仍存在,因此这些调用将不改变。

自定义格式

您自己也可以编写格式化程序,用于自己的类型或作为内置类型的自定义格式化程序,如“.NET框架开发人员指南”中的自定义Format方法所说明的那样。如果编写内置类型的自定义格式化程序,就不能从Console.WriteLine中使用它,但可以通过调用String.Format的重载而使用它,String.Format的重载将采用IServiceObjectProvider(在beta2及更高版本中称为IFormatProvider)作为参数。

C#日期格式化和时间格式

您将记起,有一个叫做DateTime的类,用于保存日期和时间。像您所猜想的那样,有大量方法可供设置DateTime对象的格式:仅日期、仅时间、世界时或本地时、若干种日/月/年顺序,甚至可分类。C#日期格式化和时间格式是区分语言的。

还可以使用自定义格式字符串来设置DateTime对象的格式。这种字符串将包含由某些字母组成的区分大小写的子字符串,以表示日期和时间的各个不同部分,如星期几、几号、月份、年份、纪元、小时、分钟、秒或时区。这些部分中有许多具有多种格式,例如,M是没有前导零的数字月份,MM是有前导零的数字月份,MMM是三个字母的月份缩写,MMMM是所在国家语言对应的完整月份名称的拼写。在“.NET框架参考”中可以找到自定义和标准格式字符的完整列表。

下面是有关C#日期格式化和时间格式的一个示例:

  1. long m34=34000000;//34,000,000
  2. Console.WriteLine("几种图片格式");
  3. Console.WriteLine("如果没有数位,0将打印0;"+
  4. "诸如i:的文字总是打印");
  5. Console.WriteLine("t句点代表小数分隔符的位置");
  6. Console.WriteLine("i,i:0000.0{0,10:i:0000.0}",i);//i:0123.0
  7. Console.WriteLine("如果没有有效数字#将不显示,"+
  8. "逗号意味着放入分隔符");
  9. Console.WriteLine("请确保在数字图片中至少使用一个0。");
  10. Console.WriteLine("p0,##,##0.#{0,10:##,##0.#}",-p0);//-31,415.9
  11. Console.WriteLine("m34,0,,{0,10:0,,百万}",m34);//34百万
  12. Console.WriteLine("p0,#0.#E+00{0,10:#0.#E+00}",p0);//31.4E+03
  13. Console.WriteLine("%乘以100并打印百分号");
  14. Console.WriteLine("pi,###0.##%{0,10:###0.##%}",pi);//314.16%
  15. Console.WriteLine("因为\而没有进行乘法运算"+
  16. "(注意:两个反斜线!)");
  17. Console.WriteLine("pi,###0.##\\%{0,10:###0.##\%}",pi);//3.14%
  18. Console.WriteLine("与C#的逐字字符串相同");
  19. Console.WriteLine(@"pi,###0.##\%{0,10:###0.##%}",pi);//3.14%
  20. Console.WriteLine("10,'#'#0{0,10:'#'#0}",10);//#10
  21. Console.WriteLine("基于符号的条件格式");
  22. Console.WriteLine("如果是0或正数打印#,如果是负数打印(#)");
  23. Console.WriteLine("-50;(0){0,10:0;(0)}",-5);//(5)
  24. Console.WriteLine("如果是正数打印#,如果是负数打印-#,如果是0打印zip");
  25. Console.WriteLine("00;-0;zip{0,10:0;-0;zip}",0);//zip