DateTime.ToString() 中带有自定义 IFormatProvider 的月份的第一个字母
First letter of month in DateTime.ToString() with custom IFormatProvider
有没有办法在 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"
如果没有,是否有某种方法可以向系统范围的 IFormatProvider 添加新的自定义格式来处理此问题?
"why are you trying to do it that way?" 用户注意事项:这是供应商的图表控件,只接受格式字符串。我们正在努力使这些日期尽可能短,并且它们是针对国际用户的,因此月份的数字将不起作用。我无法传入新的 IFormatProvider,因此我必须以某种方式 修改现有的 IFormatProvider(希望不要破坏它)。
(new DateTime(2015,1,12).ToString("MM")[0])+(new DateTime(2015,1,12).ToString("-dd-yy"))
但要小心首字母相同的月份(January 与 July),这可能会更好或更差,具体取决于其他文化。
这是一个使用自定义 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;
}
}
}
你可以这样使用它:
var monthName = DateTime.Now.ToString("MMM", SingleLetterMonthNameFormatter.FormatProvider) //First letter of month name
如果无法将 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"));
让我们深入了解一下 DateTime.ToString()
实施。当没有 IFormatProvider
对象传递给它时,它将使用 System.Globalization.DateTimeFormatInfo.CurrentInfo
作为 DateTimeFormatInfo
对象来获取有关如何构建字符串表示的信息。 CurrentInfo
,依次从 Thread.CurrentThread.CurrentCulture
.
获取
因此,您希望以一种方式设置当前线程文化,使其具有一个字符的月份名称(或缩写,如下例所示),然后使用常规格式字符串。实现此目的的一种方法如下:
using System;
using System.Globalization;
using System.Threading;
namespace DTFTest
{
class Program
{
static void Main(string[] args)
{
var dt = DateTime.Now;
Thread.CurrentThread.CurrentCulture = new CultureInfo("EN-US", true);
var ci = Thread.CurrentThread.CurrentCulture;
var monthNames = new[] { "J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", string.Empty };
ci.DateTimeFormat.AbbreviatedMonthNames = monthNames;
Console.WriteLine(dt.ToString("MMM-dd-yyyy"));
}
}
}
有没有办法在 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"
如果没有,是否有某种方法可以向系统范围的 IFormatProvider 添加新的自定义格式来处理此问题?
"why are you trying to do it that way?" 用户注意事项:这是供应商的图表控件,只接受格式字符串。我们正在努力使这些日期尽可能短,并且它们是针对国际用户的,因此月份的数字将不起作用。我无法传入新的 IFormatProvider,因此我必须以某种方式 修改现有的 IFormatProvider(希望不要破坏它)。
(new DateTime(2015,1,12).ToString("MM")[0])+(new DateTime(2015,1,12).ToString("-dd-yy"))
但要小心首字母相同的月份(January 与 July),这可能会更好或更差,具体取决于其他文化。
这是一个使用自定义 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;
}
}
}
你可以这样使用它:
var monthName = DateTime.Now.ToString("MMM", SingleLetterMonthNameFormatter.FormatProvider) //First letter of month name
如果无法将 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"));
让我们深入了解一下 DateTime.ToString()
实施。当没有 IFormatProvider
对象传递给它时,它将使用 System.Globalization.DateTimeFormatInfo.CurrentInfo
作为 DateTimeFormatInfo
对象来获取有关如何构建字符串表示的信息。 CurrentInfo
,依次从 Thread.CurrentThread.CurrentCulture
.
因此,您希望以一种方式设置当前线程文化,使其具有一个字符的月份名称(或缩写,如下例所示),然后使用常规格式字符串。实现此目的的一种方法如下:
using System;
using System.Globalization;
using System.Threading;
namespace DTFTest
{
class Program
{
static void Main(string[] args)
{
var dt = DateTime.Now;
Thread.CurrentThread.CurrentCulture = new CultureInfo("EN-US", true);
var ci = Thread.CurrentThread.CurrentCulture;
var monthNames = new[] { "J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", string.Empty };
ci.DateTimeFormat.AbbreviatedMonthNames = monthNames;
Console.WriteLine(dt.ToString("MMM-dd-yyyy"));
}
}
}