C# DateTime ToString 标准文化格式

Posted

技术标签:

【中文标题】C# DateTime ToString 标准文化格式【英文标题】:C# DateTime ToString Standard culture format 【发布时间】:2018-03-27 14:19:50 【问题描述】:

我可以更改特定文化的 DateTime 的标准输出格式吗?示例:

class Program

    static void Main(string[] args)
    
        PrintCultureDateTime("ca-ES");
        PrintCultureDateTime("es-ES");
        PrintCultureDateTime("en-US");
        PrintCultureDateTime("en-GB");
        PrintCultureDateTime("pt-PT");
    

    public static void PrintCultureDateTime(string culture)
    
        string result = new DateTime(2017, 10, 1).ToString("d", 
            CultureInfo.GetCultureInfo(culture));
        Console.WriteLine(string.Format("0: 1", culture, result));
    

输出:

ca-ES: 1/10/2017
es-ES: 01/10/2017
en-US: 10/1/2017
en-GB: 01/10/2017
pt-PT: 01/10/2017

我想要的是使用标准“d”格式或另一种标准格式使用两位数表示日期和月份,以修复 DateTime 字符串的大小。类似这样的输出:

ca-ES: 01/10/2017
es-ES: 01/10/2017
en-US: 10/01/2017
en-GB: 01/10/2017
pt-PT: 01/10/2017

【问题讨论】:

docs.microsoft.com/en-us/dotnet/standard/base-types/… Related 有趣的是,我使用您示例中的代码获得了 ca-ES 的 01/10/2017 【参考方案1】:

您可以使用DateTimeFormatInfo.ShortDatePattern 来获取模式,然后如果您真的想用dd 替换d。您可能需要考虑转义或引用d 模式等极端情况 - 以及显然不将dd 替换为dddd。 (请注意,来自系统文化的格式信息将是只读的;克隆文化以获得具有读/写格式信息的文化。)当然,您也可以这样做几个月。您甚至可能需要更改年份部分。

我不清楚这样做是个好主意 - 当您更改格式时,它不再是真正的“文化的标准短日期格式”了。

即使完成了所有这些,也不能保证所有文化的长度都相同。没有什么可以阻止一种文化使用"'Year:' yyyy '; Month: ' MM '; 'Day: 'dd" 的短日期格式。这将是非常不寻常的,但并非无效。

【讨论】:

@Marc:恐怕我现在不太确定你在说什么。 对不起@Jon-skeet,我误解了你的回答。没关系!【参考方案2】:

基于@Jon Skeet 的回答,我实施了以下解决方案。我认为必须存在具有单次迭代的更好的正则表达式替换指令,但我没有更多时间找到它。

它不适用于格式“'Year:'yyyy'; Month:'MM';'Day:'dd”,但我会假设“错误”。

    public static void PrintCultureDateTime(string culture)
    
        string result = new DateTime(2017, 10, 1).ToString(FixedSizeShortDatePattern(culture));
        Console.WriteLine(string.Format("0: 1", culture, result));
    

    public static string FixedSizeShortDatePattern(string culture)
    
        var cultureInfo = CultureInfo.GetCultureInfo(culture);
        string format = cultureInfo.DateTimeFormat.ShortDatePattern;
        return ReplaceSingleChar(ReplaceSingleChar(format, 'd'), 'M');
    

    public static string ReplaceSingleChar(string input, char c)
    
        string cStr = c.ToString();
        string strRegex = string.Format(@"^(0)[^0]|[^0](0)[^0]|[^0](0)$", cStr);
        return Regex.Replace(input, strRegex, (match) =>
        
            string token = match.Groups[0].Value;
            if (!string.IsNullOrEmpty(token))
            
                return match.Value.Replace(cStr, string.Concat(cStr, cStr));
            
            return token;
        );
    

【讨论】:

【参考方案3】:

这样的东西可能适用于大多数日期格式,但正如 Jon Skeet 所说,可能存在一些难以处理的奇怪格式。

public class CustomFormatProvider : IFormatProvider

    private string _culture;

    public CustomFormatProvider(string culture)
    
        _culture = culture;
    

    public object GetFormat(Type formatType)
    
        if (formatType.Equals(typeof(DateTimeFormatInfo)))
        
            var format = 
CultureInfo.GetCultureInfo(_culture).DateTimeFormat;
            var info = new DateTimeFormatInfo();
            switch (format.ShortDatePattern.ToString())
            
                case "d/M/yyyy":
                case "d/MM/yyyy":
                case "dd/M/yyyy":
                case "dd/MM/yyyy":
                    info.ShortDatePattern = "dd/MM/yyyy";
                    return info;
                case "M/dd/yyyy":
                case "MM/dd/yyyy":
                case "M/d/yyyy":
                case "MM/d/yyyy":
                    info.ShortDatePattern = "MM/dd/yyyy";
                    return info;
                default:
                    //This is just example for default handling
                    info.ShortDatePattern = "dd/MM/yyyy";
                    return info;
            
        
        else return null;
    

用法:

public static void PrintCultureDateTime(string culture)
    
        string result = new DateTime(2017, 10, 1).ToString("d", new 
CustomFormatProvider(culture));
        Console.WriteLine(string.Format("0: 1", culture, result));
    

输出:

【讨论】:

他可以简单地检查format.ShortDatePattern.ToString() 是否以m 开头,然后使用MM/dd/yyyy 否则使用dd/MM/yyyy 更短,并且适用于所有情况 @Franck 是的,它肯定可以重构。 因为灵感还不错,但它不适用于没有'/'作为分隔符或以年份开头的严重情况。如果需要,请查看我的解决方案并发表评论。

以上是关于C# DateTime ToString 标准文化格式的主要内容,如果未能解决你的问题,请参考以下文章

瑞典文化信息

为啥 C# decimal ToString 不请求文化和货币?

C# DateTime.ToString()的各种日期格式

C# DateTime.Now

为啥不管文化如何,C# DateTime 解析“01/05/2020”都是一样的?

难倒 C# DateTime ToString() 格式问题