C# 在DateTime.ParseExact中使用IFormatProvider的固定区域性

C# 在DateTime.ParseExact中使用IFormatProvider的固定区域性,c#,datetime,invariantculture,C#,Datetime,Invariantculture,在ParseExact方法的第一个重载中 public static DateTime ParseExact (string s, string format, IFormatProvider provider); 据微软称: 如果format是不包含日期或时间分隔符(如“yyyyMMddHHmm”)的自定义格式模式,则为提供程序参数和每个自定义格式说明符的最宽形式使用不变区域性。例如,如果要在格式模式中指定小时,请指定较宽的形式“HH”,而不是较窄的形式“H” 特别是如果我们使用标准格式模式

在ParseExact方法的第一个重载中

public static DateTime ParseExact (string s, string format, IFormatProvider provider);
据微软称:

如果format是不包含日期或时间分隔符(如“yyyyMMddHHmm”)的自定义格式模式,则为提供程序参数和每个自定义格式说明符的最宽形式使用不变区域性。例如,如果要在格式模式中指定小时,请指定较宽的形式“HH”,而不是较窄的形式“H”

特别是如果我们使用标准格式模式,我们可以使用任何其他文化


如果我们使用不包含日期或时间分隔符的自定义格式模式(如果我们使用),那么使用不变区域性和最宽的自定义说明符的真正目的是什么?

不变区域性的真正目的取自本文的答案,因为它最好地描述了它的用途:

并非所有区域性对日期和十进制/货币使用相同的格式 价值观

当您转换输入值(读取)时,这对您很重要 以字符串形式存储到DateTime、float、double或decimal。信息技术 如果您试图将上述数据类型格式化为 用于显示或存储的字符串(写入)

如果您知道您的日期和小数点对应的特定文化/ 货币值将提前输入,您可以使用该特定值 CultureInfo属性(即CultureInfo(“en GB”))。例如,如果你 期望用户输入

如果需要,则使用CultureInfo.InvariantCulture属性 格式化或分析一个字符串,该字符串应由一段 独立于用户本地设置的软件

综上所述,不变区域性将有助于转换为存储为浮点、十进制或日期时间的字符串,当您试图格式化或解析一个字符串时,它也有助于格式化或解析该字符串,该字符串应由一个软件独立于用户的本地设置进行解析,正如引文所说,这是什么

最宽自定义说明符


也就是说。

不变量文化的目的是提供一种众所周知的日期和数字格式,它不依赖于系统或用户区域设置

每次格式化不需要人类解析的内容时,都应该使用它。例如,在JSON或XML文件中,您希望以ISO格式存储日期,以避免歧义。另一方面,如果在屏幕上显示日期,则通常会尊重用户对文化的选择,并以首选方式显示


如果您使用自定义格式,那么如果可以将结果字符串解析回完全相同的日期和时间,那肯定是件好事。为了在没有分隔符的情况下做到这一点,您必须为每个组件使用固定长度的字符串

// omitting CultureInfo.InvariantCulture for brevity
var dt = new DateTime(2018,1,2,3,45,6);
dt.ToString("yyyyMMddHHmmss") // returns "20180102034506"
dt.ToString("yyyyMdHms")      // returns "2018123456"

您可以很容易地看到,第二个日期不是唯一的,也就是说,其他日期将返回相同的字符串。为了避免使用每个组件的更广泛形式。

对于初学者,格式模式(如
MM
)仍然是特定于区域性的。Per:“MM”自定义格式说明符将月份表示为从01到12的数字(对于有13个月的日历,则表示为从1到13的数字)。”要排除所有此类变化,明确说明固定区域性有助于。(另外,如果使用不变区域性,框架中的几个代码路径使用优化的变体,尽管我不知道
DateTime.ParseExact
是否是其中之一。)
// omitting CultureInfo.InvariantCulture for brevity
var dt = new DateTime(2018,1,2,3,45,6);
dt.ToString("yyyyMMddHHmmss") // returns "20180102034506"
dt.ToString("yyyyMdHms")      // returns "2018123456"