【问题标题】:How to format a date in C# by example?如何通过示例在 C# 中格式化日期?
【发布时间】:2011-09-29 18:29:05
【问题描述】:

在为字符串表示格式化 DateTime 对象时,C# 提供了很大的灵活性,但是,必须了解所有格式字符串才能使用这种灵活性。

如果你想以“Fri, June 24”的形式显示一个日期,你可以这样做:

DateTime someDate = DateTime.Now;
Console.Write(someDate.ToString("ddd, MMMM dd"));

虽然这很好用,但对于更复杂的格式来说很难,尤其是对于第一次使用它的开发人员。

我想获得与上面代码返回的结果相同的结果,但是这样:

DateTime someDate = DateTime.Now;
Console.WriteLine(someDate.ToString("Wed, June 12"));

指定为字符串的日期可以是任意的。本质上,格式必须通过首先以某种方式解析日期来确定。我知道这种方法有局限性(本地化就是其中之一),但对于简单的场景,它更容易理解。除了自己实现之外,还有什么方法可以做到吗?我愿意使用第三方库。

【问题讨论】:

  • 我不认为后者更具可读性。
  • 如何计算 dd/MM/yy 和 MM/dd/yyyy 之间的差异?
  • 抱歉,someDate.ToString("ddd, MMMM dd") 对我来说已经够清楚了...
  • 我觉得你的方法很不直观——只要学习格式字符串,学习起来并不难。
  • @Slavo,学习这个框架所做的假设和模棱两可调用的默认值不是更好地用于学习格式字符串或如何查找它们吗?

标签: c# .net datetime format


【解决方案1】:

我认为这行不通,你怎么知道12 是一天还是一年。我认为现有的歧义实际上会比学习相对简单的自定义格式字符串更复杂。

您曾经使用过 VBA 和日期吗?

【讨论】:

  • 我认为如果你修复一天使用它可能会起作用。在您的图书馆中选择一个特殊的日子,例如 2011 年 9 月 12 日,它不能以任何形式重叠。
  • @Scorpi - 您需要使用第 13 天和第 32 年来消除所有歧义 - 例如 2032 年 9 月 13 日。2011 年 11 月 12 日仍然模棱两可...是月、日还是第一年?
  • @Gavin Coates 我不太清楚如何礼貌地说这句话,所以我就直说吧。九月是第九个月,不是第十一个月。 :) 但是,您的观点是:2011 年 9 月 12 日仍然不清楚哪一部分是哪一部分!
  • 您必须有一个尽可能多格式的明确日期。不幸的是,它会发生冲突:要指示哪个是日、月和两位数的年份,您需要一个天>=13 和一个年>31。但是要表示小于 10 的日期和月份是使用一位还是两位数字,您需要小于 10 的日期和月份...
【解决方案2】:

通常我只是找出正确的格式字符串应该是什么(在您的示例中为"ddd, MMMM dd"),然后将其作为常量存储在应用程序的某个位置...

public static class DateTimeFormats
{
    public string DayOfWeekMonthDay = "ddd, MMMM dd";
}

那你可以参考一下

DateTime.Now.ToString(DateTimeFormats.DayOfWeekMonthDay)

【讨论】:

  • 这不会为您节省第一次查找的时间,对吗?
  • @Slavo,不,但它可以节省您围绕插件编写/配置和维护代码来为您执行此操作。
  • 不会,但您永远不必再查找它,查找起来非常简单......这是一个链接msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
  • @Jodrell:这个问题的正确答案是“你不能那样做”。所以我认为@Jon 在这里的回答非常好。
  • 这是一个很好的方法,提高了维护的可读性并且非常干燥/有利于一致性。
【解决方案3】:

这个问题的严格答案:

除了 自己实施?我愿意 使用第三方库。

不是,除非第三方已经这样做了,否则您需要实现自己的格式字符串解析器。

我同意大多数受访者的观点,即这样做所需的努力与简单地记住已经提供的 DateTime 格式(或参考他们的文档)的替代方法完全不成比例。但是,如果您确实进行了这样的努力,您可能希望实现一个 ICustomFormatter 和一个 IFormatProvider,以便在请求时提供它。

有关示例,请参阅上面链接的 ICustomFormatter 文档,但您的任务将涉及提供一个 Format(string format, object arg, IFormatProvider formatProvider) 方法,该方法采用 感兴趣的格式的字符串并使用它来转换传递的 DateTime在arg 中转换为与该模式匹配的字符串。

一旦完成,并且您有一个 IFormatProvider,其 GetFormat() 方法返回您的自定义格式化程序,您的示例代码将如下所示:

DateTime someDate = DateTime.Now;
Console.WriteLine(someDate.ToString("Wed, June 12", new CustomDateFormatter()));

【讨论】:

  • 猜猜看 - 出于好奇,我尝试实现自己的格式化程序和格式提供程序,但没有成功。反映 DateTime.ToString() 的代码表明您应该始终从 GetFormat 返回一个 DateTimeFormatInfo 对象,并且永远不会调用您的 ICustomFormatter 实现。这是 .NET 中的错误还是故意的?
【解决方案4】:

我可以看到这对于新开发人员来说似乎更容易使用,但是在构建“日期字符串的日期格式”函数时需要解决一些问题。我可以想象这样的功能可能会失败的场景,比如:

  • 你说的是“五月”;这是否意味着 June 中的日期应该格式化为“Jun”或“June”?
  • 您说的是“6 月 12 日”;这是否意味着 June 5th 应该格式化为“June 5”或“June 05”?

现在,您可以向新开发人员解释他们需要注意不要使用模棱两可的示例日期格式模板。但这需要他们已经理解它可能是如何模棱两可的。他们需要已经像格式化函数那样思考。

这就是为什么要按原样定义日期格式字符串的原因 - 尽可能具体地说明开发人员想要/需要生成的所需输出格式。它们最大程度地防止了这种歧义。

如果开发人员最终需要“像格式化函数一样思考”来获得他们想要的东西,那么可能值得花时间学习现有的定义。

【讨论】:

    【解决方案5】:

    在搜索了一段时间后,我设法找到了一个 Ruby library,它与我正在寻找的东西完全相同。由于找不到 .NET 解决方案,我实现了自己的实用程序,灵感来自 Ruby。

    可以在 github 上看到支持 4 种常见格式的尖峰 - Stamp.Net。我将其发布为答案,以便对此类实用程序感兴趣的人可以从那里获取它并直接在他们的项目中使用它。

    请注意,当前状态只是证明一个观点,是一个实验。没有进行单元测试。欢迎您的 cmets。

    一些实现说明:

    .NET 框架提供了一种非常好的方法来实现自定义格式化程序和类型的格式提供程序。 @djacobson 在回答问题时提到了这一点。不幸的是,DateTime 类的实现方式是您不能将 ICustomFormatter 与它一起使用。当您使用自定义格式提供程序调用 ToString() 时,该格式提供程序必须返回一个 DateTimeFormatInfo 对象,并且 DateTime 类不会调用从格式提供程序返回的自定义格式化程序。

    已通过在 DateTime 类上实现自定义扩展方法来解决此问题,该方法直接调用自定义格式化程序。图书馆的用户无需担心这些细节。

    【讨论】:

      猜你喜欢
      • 2010-10-04
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      相关资源
      最近更新 更多