【问题标题】:Getting day suffix when using DateTime.ToString()使用 DateTime.ToString() 时获取日期后缀
【发布时间】:2011-01-04 06:45:13
【问题描述】:

使用 DateTime.ToString() 格式化日期时是否可以包含日期后缀?

例如,我想按以下格式打印日期 - 2009 年 7 月 27 日星期一。但是,我可以使用 DateTime.ToString() 找到的最接近的示例是 2009 年 7 月 27 日星期一。

我可以使用 DateTime.ToString() 来做到这一点,还是我必须回退到我自己的代码?

【问题讨论】:

  • 有人说 NodaTime 吗?
  • 仅供参考,“[日期] 序数后缀”就是这些名称。 “日”通常指周一至周日
  • @grenade 我希望这是一个糟糕的答案。我一直在寻找一个小时的大部分时间来格式化问题中提到的 NodaTime,但据我所知它不起作用:nodatime.org/2.3.x/userguide/localdate-patterns(即使在 2020 年)看起来 momentjs 有这个,因为他们建立了自己的本地化模型:momentjs.com/docs/#/i18n
  • nodatime.org/3.0.x/userguide/limitations 此外,我们所有的文本本地化资源(日期和月份名称)都来自 .NET 框架本身。这有一些明显的局限性,并且使得 Noda Time 对 CultureInfo 的依赖程度超过了理想情况。 CLDR 包含更多信息,应该允许诸如序数天数(“1st”、“2nd”、“3rd”)和更广泛的支持日历/文化组合(例如希伯来日历月的英文名称)等功能。

标签: c# .net date


【解决方案1】:

作为参考,我总是使用/参考 [SteveX 字符串格式] 1 并且任何可用变量中似乎都没有任何“th”,但您可以轻松地构建一个字符串

string.Format("{0:dddd dd}{1} {0:MMMM yyyy}", DateTime.Now, (?));

然后,您必须为 1 提供“st”,为 2 提供“nd”,为 3 提供“rd”,为所有其他提供“th”,并且可以内嵌“?:”语句。

var now = DateTime.Now;
(now.Day % 10 == 1 && now.Day % 100 != 11) ? "st"
: (now.Day % 10 == 2 && now.Day % 100 != 12) ? "nd"
: (now.Day % 10 == 3 && now.Day % 100 != 13) ? "rd"
: "th"

【讨论】:

  • 这需要进一步扩展以涵盖其他情况,否则您最终会得到“21th”,例如。
  • 对于它的价值,可以找到微软的字符串格式化选项的官方文档here
  • DateTime.Now 在同一个表达式中被多次检索,如果代码在午夜左右执行,则值可能不同。
  • 我修复了代码以处理超过 100 的数字,因此您现在将获得 112th 而不是 112nd
  • @Jez 我认为没有超过 100 的日期,请检查 Microsoft Doc docs.microsoft.com/en-us/dotnet/api/system.datetime.day 以前的答案编辑必须是正确的:stackoverflow.com/revisions/2050854/4 并重新支持您的更改
【解决方案2】:
string datestring;    
// datestring = DateTime.Now.ToString("dd MMMM yyyy"); // 16 January 2021

    // code to add 'st' ,'nd', 'rd' and 'th' with day of month 
    // DateTime todaysDate = DateTime.Now.Date; // enable this line for current date 
    DateTime todaysDate = DateTime.Parse("01-13-2021"); // custom date to verify code // 13th January 2021
    int day = todaysDate.Day;
    string dateSuffix;

    if(day==1 || day==21 || day==31){
        dateSuffix= "st";
    }else if(day==2 || day==22 ){
        dateSuffix= "nd";
    }else if(day==3 || day==23 ){
        dateSuffix= "rd";
    }else{
        dateSuffix= "th";
    }
    datestring= day+dateSuffix+" "+todaysDate.ToString("MMMM")+" "+todaysDate.ToString("yyyy");
    Console.WriteLine(datestring);

【讨论】:

    【解决方案3】:

    查看humanizr: https://github.com/Humanizr/Humanizer#date-time-to-ordinal-words

    new DateTime(2015, 1, 1).ToOrdinalWords() => "1st January 2015"
    new DateTime(2015, 2, 12).ToOrdinalWords() => "12th February 2015"
    new DateTime(2015, 3, 22).ToOrdinalWords() => "22nd March 2015"
    // for English US locale
    new DateTime(2015, 1, 1).ToOrdinalWords() => "January 1st, 2015"
    new DateTime(2015, 2, 12).ToOrdinalWords() => "February 12th, 2015"
    new DateTime(2015, 3, 22).ToOrdinalWords() => "March 22nd, 2015"
    

    我在发布此帖子后立即意识到@Gumzle 提出了同样的建议,但我错过了他的帖子,因为它被埋在了代码 sn-ps 中。所以这是他的答案,有足够的代码让某人(比如我)快速滚动浏览可能会看到它。

    【讨论】:

      【解决方案4】:

      对于那些乐于使用外部依赖的人(在本例中是奇妙的Humanizr .net),就像

      dateVar.Day.Ordinalize(); \\ 1st, 4th etc depending on the value of dateVar

      【讨论】:

      • 很好的建议。我希望这是内置到 .NET 中的。
      【解决方案5】:

      使用几个扩展方法:

      namespace System
      {
          public static class IntegerExtensions
          {
              public static string ToOccurrenceSuffix(this int integer)
              {
                  switch (integer % 100)
                  {
                      case 11:
                      case 12:
                      case 13:
                          return "th";
                  }
                  switch (integer % 10)
                  {
                      case 1:
                          return "st";
                      case 2:
                          return "nd";
                      case 3:
                          return "rd";
                      default:
                          return "th";
                  }
              }
          }   
      
          public static class DateTimeExtensions
          {
              public static string ToString(this DateTime dateTime, string format, bool useExtendedSpecifiers)
              {
                  return useExtendedSpecifiers 
                      ? dateTime.ToString(format)
                          .Replace("nn", dateTime.Day.ToOccurrenceSuffix().ToLower())
                          .Replace("NN", dateTime.Day.ToOccurrenceSuffix().ToUpper())
                      : dateTime.ToString(format);
              } 
          }
      }
      

      用法:

      return DateTime.Now.ToString("dddd, dnn MMMM yyyy", useExtendedSpecifiers: true);
      // Friday, 7th March 2014
      

      注意:整数扩展方法可以用于任何数字,而不仅仅是 1 到 31。例如

      return 332211.ToOccurrenceSuffix();
      // th
      

      【讨论】:

      • 谢谢哥们。很有帮助。我已经在我的项目中实现了。 :)
      • 你的代码有点...忘记检查useExtendedSpecifiers boolean :p
      • 最优雅的解决方案。这正是扩展方法的设计目的。已添加到我不断增长的扩展方法库中,谢谢!
      • ToOrdinal(),也许吧? :)
      【解决方案6】:

      更新

      NuGet 包:
      https://www.nuget.org/packages/DateTimeToStringWithSuffix

      示例:
      https://dotnetfiddle.net/zXQX7y

      支持:
      .NET Core 1.0 及更高版本
      .NET Framework 4.5 及更高版本


      这是一个扩展方法(因为每个人都喜欢扩展方法),以 Lazlow 的答案为基础(选择 Lazlow 的,因为它易于阅读)。

      DateTime 上的常规ToString() 方法一样工作,但如果格式包含ddd,则会自动添加后缀。

      /// <summary>
      /// Return a DateTime string with suffix e.g. "st", "nd", "rd", "th"
      /// So a format "dd-MMM-yyyy" could return "16th-Jan-2014"
      /// </summary>
      public static string ToStringWithSuffix(this DateTime dateTime, string format, string suffixPlaceHolder = "$") {
          if(format.LastIndexOf("d", StringComparison.Ordinal) == -1 || format.Count(x => x == 'd') > 2) {
              return dateTime.ToString(format);
          }
      
          string suffix;
          switch(dateTime.Day) {
              case 1:
              case 21:
              case 31:
                  suffix = "st";
                  break;
              case 2:
              case 22:
                  suffix = "nd";
                  break;
              case 3:
              case 23:
                  suffix = "rd";
                  break;
              default:
                  suffix = "th";
                  break;
          }
      
          var formatWithSuffix = format.Insert(format.LastIndexOf("d", StringComparison.InvariantCultureIgnoreCase) + 1, suffixPlaceHolder);
          var date = dateTime.ToString(formatWithSuffix);
      
          return date.Replace(suffixPlaceHolder, suffix);
      }
      

      【讨论】:

      • 很惊讶这没有得到更多的支持,我更喜欢它是一个扩展的事实。使其更易于使用,并且可以说更具可读性。
      • 那个 NuGet 包不喜欢包含 ddddddd 的格式 - 即工作日的名称。如果您想将日期显示为“2021 年 11 月 4 日星期四”,则需要解决该限制 - 例如 Console.WriteLine(DateTime.UtcNow.ToString("dddd")+" "+DateTime.UtcNow.ToStringWithSuffix("d MMMM yyyy"));
      【解决方案7】:

      另一个选项是使用Modulo Operator

      public string CreateDateSuffix(DateTime date)
      {
          // Get day...
          var day = date.Day;
      
          // Get day modulo...
          var dayModulo = day%10;
      
          // Convert day to string...
          var suffix = day.ToString(CultureInfo.InvariantCulture);
      
          // Combine day with correct suffix...
          suffix += (day == 11 || day == 12 || day == 13) ? "th" :
              (dayModulo == 1) ? "st" :
              (dayModulo == 2) ? "nd" :
              (dayModulo == 3) ? "rd" :
              "th";
      
          // Return result...
          return suffix;
      }
      

      然后您可以通过传入一个 DateTime 对象作为参数来调用上述方法,例如:

      // Get date suffix for 'October 8th, 2019':
      var suffix = CreateDateSuffix(new DateTime(2019, 10, 8));
      

      有关 DateTime 构造函数的详细信息,请参阅Microsoft Docs Page

      【讨论】:

      • @Greg 这很奇怪,因为 var suffix = CreateDateSuffix(new DateTime(2013, 10, 8)); 在我的情况下返回 '8th'?
      • 如果将 'th' 附加到字符串 '8' 是错误的,但在这种情况下,因为您使用了数字 8,所以它是正确的。
      • 上述方法采用 DateTime 对象,我看不到如何用除数值以外的任何值来实例化它 - 在本例中为 '8' 代表月份中的某一天。
      • 在这种情况下,它是正确的。如果你要,我不知道,用数字的文本表示替换数值,那将是错误的。我想这取决于进行替换的人,要知道这一点并将“8t”替换为“8”,或者更准确地说,将“8”替换为“eigh”。
      【解决方案8】:

      获取日期后缀。 (静态函数)

      public static string GetSuffix(this string day)
      {
          string suffix = "th";
      
          if (int.Parse(day) < 11 || int.Parse(day) > 20)
          {
              day = day.ToCharArray()[day.ToCharArray().Length - 1].ToString();
              switch (day)
              {
                  case "1":
                      suffix = "st";
                      break;
                  case "2":
                      suffix = "nd";
                      break;
                  case "3":
                      suffix = "rd";
                      break;
              }
          }
      
          return suffix;
      }
      

      参考:https://www.aspsnippets.com/Articles/Display-st-nd-rd-and-th-suffix-after-day-numbers-in-Formatted-Dates-using-C-and-VBNet.aspx

      【讨论】:

        【解决方案9】:

        public static String SuffixDate(DateTime 日期) { 字符串序数;

             switch (date.Day)
             {
                case 1:
                case 21:
                case 31:
                   ordinal = "st";
                   break;
                case 2:
                case 22:
                   ordinal = "nd";
                   break;
                case 3:
                case 23:
                   ordinal = "rd";
                   break;
                default:
                   ordinal = "th";
                   break;
             }
             if (date.Day < 10)
                return string.Format("{0:d}{2} {1:MMMM yyyy}", date.Day, date, ordinal);
             else
                return string.Format("{0:dd}{1} {0:MMMM yyyy}", date, ordinal);
          }
        

        【讨论】:

        • 这个版本只显示一天的第一个数字,即 2017 年 3 月 1 日,我不想把日期名称放在第一位,因为我不想在长日期中将日期名称放在第一位,也不想要 01 号而不是 1 号
        【解决方案10】:

        以@Lazlow 的回答完整解决方案,以下是完全可重用的扩展方法,并附示例用法;

        internal static string HumanisedDate(this DateTime date)
        {
            string ordinal;
        
            switch (date.Day)
            {
                case 1:
                case 21:
                case 31:
                    ordinal = "st";
                    break;
                case 2:
                case 22:
                    ordinal = "nd";
                    break;
                case 3:
                case 23:
                    ordinal = "rd";
                    break;
                default:
                    ordinal = "th";
                    break;
            }
        
            return string.Format("{0:dddd dd}{1} {0:MMMM yyyy}", date, ordinal);
        } 
        

        要使用它,您只需在 DateTime 对象上调用它;

        var myDate = DateTime.Now();
        var myDateString = myDate.HumanisedFormat()
        

        这会给你:

        2016 年 6 月 17 日星期五

        【讨论】:

          【解决方案11】:

          这里的价值是我使用以下答案的最终解决方案

               DateTime dt = DateTime.Now;
                  string d2d = dt.ToString("dd").Substring(1); 
          
                  string suffix =
                 (dt.Day == 11 || dt.Day == 12 || dt.Day == 13) ? "th"
                 : (d2d == "1") ? "st"
                 : (d2d == "2") ? "nd"
                 : (d2d == "3") ? "rd"
                 : "th";
          
          
                  Date.Text = DateTime.Today.ToString("dddd d") + suffix + " " + DateTime.Today.ToString("MMMM") + DateTime.Today.ToString(" yyyy"); 
          

          【讨论】:

            【解决方案12】:

            另一个使用开关的选项:

            string GetDaySuffix(int day)
            {
                switch (day)
                {
                    case 1:
                    case 21:
                    case 31:
                        return "st";
                    case 2:
                    case 22:
                        return "nd";
                    case 3:
                    case 23:
                        return "rd";
                    default:
                        return "th";
                }
            }
            

            【讨论】:

            • +1 简单易读,最重要的是,适用于所有情况。
            • @tobias_k 谢谢 - 我想知道我微不足道的名声是如何迅速翻倍的!
            • 对于那些想要完整日期格式的人: return date.ToString("dd MMMM yyyy").Insert(2, GetDaySuffix(date.Day)); //例如 2020 年 1 月 12 日
            【解决方案13】:

            一个便宜又好用的 VB 解决方案:

            litDate.Text = DatePart("dd", Now) & GetDateSuffix(DatePart("dd", Now))
            
            Function GetDateSuffix(ByVal dateIn As Integer) As String
            
                '// returns formatted date suffix
            
                Dim dateSuffix As String = ""
                Select Case dateIn
                    Case 1, 21, 31
                        dateSuffix = "st"
                    Case 2, 22
                        dateSuffix = "nd"
                    Case 3, 23
                        dateSuffix = "rd"
                    Case Else
                        dateSuffix = "th"
                End Select
            
                Return dateSuffix
            
            End Function
            

            【讨论】:

              【解决方案14】:

              我是这样做的,它解决了其他示例中给出的一些问题。

                  public static string TwoLetterSuffix(this DateTime @this)
                  {
                      var dayMod10 = @this.Day % 10;
              
                      if (dayMod10 > 3 || dayMod10 == 0 || (@this.Day >= 10 && @this.Day <= 19))
                      {
                          return "th";
                      }
                      else if(dayMod10 == 1)
                      {
                          return "st";
                      }
                      else if (dayMod10 == 2)
                      {
                          return "nd";
                      }
                      else
                      {
                          return "rd";
                      }
                  }
              

              【讨论】:

                【解决方案15】:

                我相信这是一个很好的解决方案,涵盖了诸如 111th 等数字:

                private string daySuffix(int day)
                {
                    if (day > 0)
                    {
                        if (day % 10 == 1 && day % 100 != 11)
                            return "st";
                        else if (day % 10 == 2 && day % 100 != 12)
                            return "nd";
                        else if (day % 10 == 3 && day % 100 != 13)
                            return "rd";
                        else
                            return "th";
                    }
                    else
                        return string.Empty;
                }
                

                【讨论】:

                • 虽然这是一种更通用的方法,但适用于任何数字,而不仅仅是月日(我认为)。
                【解决方案16】:

                使用最后一个字符串字符的另一个选项:

                public static string getDayWithSuffix(int day) {
                 string d = day.ToString();
                 if (day < 11 || day > 13) {
                  if (d.EndsWith("1")) {
                   d += "st";
                  } else if (d.EndsWith("2")) {
                   d += "nd";
                  } else if (d.EndsWith("3")) {
                   d += "rd";
                  } else {
                   d += "th";
                 } else {
                  d += "th";
                 }
                 return d;
                }
                

                【讨论】:

                • 感谢 AakashM 你的权利,我已经编辑以纠正错误。
                • 现在它给出了1th2th3th
                【解决方案17】:

                这里是11、12、13的加长版:

                DateTime dt = DateTime.Now;
                string d2d = dt.ToString("dd").Substring(1);
                string daySuffix =
                    (dt.Day == 11 || dt.Day == 12 || dt.Day == 13) ? "th"
                    : (d2d == "1") ? "st"
                    : (d2d == "2") ? "nd"
                    : (d2d == "3") ? "rd"
                    : "th";
                

                【讨论】:

                • 那么“11th”、“12th”和“13th”呢?
                • 我一定错过了这个。我在上面解决了这个问题。
                • 仅供参考,如果大于("dd") 产生的数字需要这样做,请使用string.PadLeft()
                • @PiotrLewandowski - 你不是来自曼彻斯特吗?因为我从那里认识一个。太古怪了+1顺便说一句
                【解决方案18】:

                在 MSDN 文档中,没有提到可以将 17 转换为 17 的文化。所以你应该通过代码隐藏手动完成。或者构建一个......你可以构建一个函数来做到这一点。

                public string CustomToString(this DateTime date)
                    {
                        string dateAsString = string.empty;
                        <here wright your code to convert 17 to 17th>
                        return dateAsString;
                    }
                

                【讨论】:

                  猜你喜欢
                  • 2020-04-04
                  • 1970-01-01
                  • 2012-02-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-10-19
                  • 1970-01-01
                  • 2016-11-14
                  相关资源
                  最近更新 更多