【问题标题】:NLog use Persian Calendar Date formatNLog 使用波斯日历日期格式
【发布时间】:2014-11-06 07:30:50
【问题描述】:

我对在我的 C# 项目中使用 NLog 很感兴趣,发现它很棒,但是
在我的国家,客户使用“波斯日历”。
如您所知,Microsoft 开发了一个库来支持名为“C# Persian Calendar 类”。
我需要两个地方的波斯日历日期格式
1-消息时间戳
基于 2 日期的文件名
如何强制 NLog 在上述用法中使用“C#波斯日历类”?
谢谢

【问题讨论】:

    标签: c# calendar nlog persian


    【解决方案1】:

    您不必修改 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));
            }
        }
    }
    

    祝你好运!

    【讨论】:

    • 太好了,非常感谢。工作,但它应该首先注册 >>NLog.Config.ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("persiandate", typeof(PersianDateLayoutRenderer));>if (!NLog.Config .ConfigurationItemFactory.Default.LayoutRenderers.AllRegisteredItems.ContainsKey("persianlongdate"))
    【解决方案2】:

    这样做有两个困难:

    • 您需要弄清楚在这两种情况下如何执行格式化,并了解如何自定义它,例如通过指定不同的文化或格式委托
    • 波斯日历目前不是任何文化的可选日历,因此使用 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
    

    【讨论】:

    • 谢谢,据我了解,我应该使用 NLog 源代码而不是 lib 并实现/更改/添加波斯格式。它很好,但在 NLog 的每个版本中,我都应该在源代码上再做一次。但这是迄今为止唯一的方法。再次感谢您的建议。
    • @MohTarvirdi:理想情况下,您应该考虑使其足够灵活,以便您可以将您的代码(不会特定于 PersianCalendar)贡献回 NLog,然后只有 PersianCalendar 特定的部分在您的代码中,然后可以跨多个 NLog 版本工作。但这将取决于您对 NLog 的灵活性的研究结果。
    猜你喜欢
    • 2018-10-05
    • 1970-01-01
    • 2023-03-30
    • 2014-09-19
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多