带有自定义IFormatProvider的DateTime.ToString()中的第一个月份

snu*_*mpy 5 c# datetime tostring string-formatting

DateTime格式字符串中是否有一种方法只包含该月的第一个字母?

new DateTime(2015, 1, 12).ToString("M-dd-yy") // "1-12-15",  but I want "J-02-15"
new DateTime(2000, 11, 7).ToString("M-dd-yy") // "11-07-00", but I want "N-17-00"
Run Code Online (Sandbox Code Playgroud)

如果没有,是否有某种方法可以将新的自定义格式添加到系统范围的IFormatProvider来处理这个问题?

请注意"你为什么要这样做?" people:这是供应商的图表控件,只接受格式字符串.我们正在努力使这些日期尽可能短,并且它们适用于国际用户,因此本月的数字将无效.我无法传递新的IFormatProvider,因此我必须以某种方式修改现有的IFormatProvider(希望不会破坏它).

brz*_*brz 3

这是使用定制的解决方案FormatProvider

    public static class SingleLetterMonthNameFormatter
    {
        private static IFormatProvider _formatProvider;
        public static IFormatProvider FormatProvider
        {
            get
            {
                if (_formatProvider == null)
                {
                    var dtfi = new DateTimeFormatInfo();
                    dtfi.AbbreviatedMonthNames = dtfi.MonthNames.Select(x => x.FirstOrDefault().ToString()).ToArray();
                    _formatProvider = dtfi;
                }
                return _formatProvider;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它:

var monthName = DateTime.Now.ToString("MMM", SingleLetterMonthNameFormatter.FormatProvider) //First letter of month name
Run Code Online (Sandbox Code Playgroud)

如果无法将 a 传递FormatProvider给您想要的方法,那么有一种糟糕的方法可以做到这一点,请小心使用!

    var currentCulture = Thread.CurrentThread.CurrentCulture.Clone() as CultureInfo;
    currentCulture.DateTimeFormat = SingleLetterMonthNameFormatter.FormatProvider as DateTimeFormatInfo;
    Thread.CurrentThread.CurrentCulture = currentCulture;
    Console.WriteLine(DateTime.Now.ToString("MMM"));
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案,我没有意识到当前的文化实例是公开的。您可能应该添加一些有关这可能会破坏的信息(该线程上对 DateTime.ToString 的任何其他调用实际上想要使用缩写的 3 字母月份名称),并且还要注意,如果供应商在另一个线程上调用 ToString,则这将不起作用线 (2认同)