【发布时间】:2014-11-06 07:30:50
【问题描述】:
我对在我的 C# 项目中使用 NLog 很感兴趣,发现它很棒,但是
在我的国家,客户使用“波斯日历”。
如您所知,Microsoft 开发了一个库来支持名为“C# Persian Calendar 类”。
我需要两个地方的波斯日历日期格式
1-消息时间戳
基于 2 日期的文件名
如何强制 NLog 在上述用法中使用“C#波斯日历类”?
谢谢
【问题讨论】:
我对在我的 C# 项目中使用 NLog 很感兴趣,发现它很棒,但是
在我的国家,客户使用“波斯日历”。
如您所知,Microsoft 开发了一个库来支持名为“C# Persian Calendar 类”。
我需要两个地方的波斯日历日期格式
1-消息时间戳
基于 2 日期的文件名
如何强制 NLog 在上述用法中使用“C#波斯日历类”?
谢谢
【问题讨论】:
您不必修改 NLog 源并自己构建它。您可能可以编写自己的 PersianDateLayoutRenderer。然后将 NLog 配置为使用您的布局渲染器而不是 NLog 的内置布局渲染器是一件简单的事情。当您升级到新版本的 NLog 时,您的布局渲染器应该仍然可以工作。
这是一个结合了 NLog 的 LongDateLayoutRenderer 和 .NET Persian Calendar 的示例。我不知道格式是否适用于波斯日期,所以我只是硬编码了一个格式。
您可以在 NLog.config 文件中使用 ${persianlongdate} 而不是 ${shortdate}、${longdate} 或 ${date} 进行配置。
我没有尝试构建或运行它,但它应该非常接近。如果您决定尝试这条路线,您可以轻松修改它以使用 Jon 的 Noda Time。
您可以在此处找到 NLog 的 LongDateLayoutRenderer(以及 DateLayoutRenderer 和 ShortDateLayoutRenderer)的来源:
https://github.com/NLog/NLog/blob/master/src/NLog/LayoutRenderers
namespace MyLayoutRenderers
{
using System.ComponentModel;
using System.Globalization;
using System.Text;
using NLog.Config;
[LayoutRenderer("persianlongdate")]
[ThreadAgnostic]
public class PersianSLongDateLayoutRenderer : LayoutRenderer
{
PersianCalendar pc = new PersianCalendar();
/// <summary>
/// Gets or sets a value indicating whether to output UTC time instead of local time.
/// </summary>
/// <docgen category='Rendering Options' order='10' />
[DefaultValue(false)]
public bool UniversalTime { get; set; }
/// <summary>
/// Renders the current short date string (yyyy-MM-dd) and appends it to the specified <see cref="StringBuilder" />.
/// </summary>
/// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
/// <param name="logEvent">Logging event.</param>
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
DateTime ts = logEvent.TimeStamp;
//Not sure if UniversalTime makes sense for PersianCalendar. Do you?
if (this.UniversalTime)
{
ts = ts.ToUniversalTime();
}
builder.Append(String.Format("{0}-{1}-{2}-{3}:{4}-{5}-{6}",
pc.GetDayOfWeek(ts),
pc.GetMonth(ts),
pc.GetDayOfMonth(ts),
pc.GetYear(ts),
pc.GetHour(ts),
pc.GetMinute(ts),
pc.GetSecond(ts));
}
}
}
祝你好运!
【讨论】:
这样做有两个困难:
DateTime.ToString 无论如何都不起作用:(您肯定需要查看 NLog 的源代码(或至少是文档),以了解是否有配置格式的方法。一旦你弄清楚如何让你自己的代码在那里执行 - 例如通过编写自己的子类,可能 - 您需要弄清楚如何进行实际格式化。
您可以使用 BCL 执行此操作,调用 PersianCalendar 并进行简单的数字格式化。或者你可以使用我的Noda Time 库,它也支持波斯日历(从 Noda Time 1.3 开始)。你会想要这样的东西:
var gregorian = new LocalDate(2014, 11, 6); // Or whatever
var persian = gregorian.WithCalendar(CalendarSystem.GetPersianCalendar());
var text = persian.ToString("yyyy-MM-dd"); // Or create a LocalDatePattern
【讨论】: