C#で序数を作成する簡単な方法はありますか?


202

C#で数値の数を作成する簡単な方法はありますか?例えば:

  • 1は1番目を返します
  • 2は2番目を返します
  • 3は3番目を返します
  • ...等

これを介して実行できますか、これを実行するString.Format()ために使用できる機能はありますか?

回答:


311

このページには、すべてのカスタム数値フォーマットルールの完全なリストが表示されます。

http://msdn.microsoft.com/en-us/library/0c899ak8.aspx

ご覧のとおり、序数については何もないため、String.Formatを使用して行うことはできません。しかし、それを行う関数を書くのはそれほど難しいことではありません。

public static string AddOrdinal(int num)
{
    if( num <= 0 ) return num.ToString();

    switch(num % 100)
    {
        case 11:
        case 12:
        case 13:
            return num + "th";
    }

    switch(num % 10)
    {
        case 1:
            return num + "st";
        case 2:
            return num + "nd";
        case 3:
            return num + "rd";
        default:
            return num + "th";
    }
}

更新:技術的には0以下の序数は存在しないため、上記のコードを更新しました。冗長なToString()メソッドも削除されました。

また、これは国際化されていません。他の言語での序数がどのように見えるか私にはわかりません。


2
Assert.AreEqual( "0"、AddOrdinal(0)); wisegeek.com/what-is-an-ordinal-number.htmを
si618

2
拡張メソッド(またはそれと呼ばれるもの-@Stuの回答を参照)を使用すると、ここでうまく機能します。@Si、その条件を追加することは、必要であれば非常に簡単です。
ストレッジャー2009年

12
「11日、12日、13日」について忘れてしまった...インタビューの質問でなければなりません。:-)
Holf 2012年

2
ええ、プログラマーは奇妙です;)
samjudson '19年

2
@IanWarburton単一のreturnステートメントのみがヒットするため、冗長性はありません。答えに満足できない場合は、独自に入力してください。これを行う「適切な」方法と、それが重要である理由を示してください。
B2K 2017

73

国際化を忘れないでください!

ここでのソリューションは英語でのみ機能します。他の言語をサポートする必要がある場合、状況はさらに複雑になります。

たとえば、スペイン語では、「1st」は、カウントしているものが男性、女性、または複数であるかどうかに応じて、「1.o」、「1.a」、「1.os」、または「1.as」と表記されます。 !

したがって、ソフトウェアが異なる言語をサポートする必要がある場合は、序数を避けてください。


7
@ Andomar:「最初の2人の読者」=>イタリア語(スペイン語もそうだと思います)では、「最初」は複数形です。つまり、単数形の男性、単数形の女性、複数形の男性、複数形の女性があります。多分いくつかの言語は中立的なケースも持っています(男性/動物と区別する)
M.Turrini 09年

2
とはいえ、序数を回避する必要はありません。直面する可能性のあるすべてのケースがわかったら、序数をローカライズに含めるか、または(顧客に)いくつかの制限を受け入れます。
M.Turrini 2009年

26
これが、.NETチームがそれをDateTimeフォーマッタに追加しないことを明らかにした理由を説明しています
Chris S

moment.jsはロケールごとに「通常の」フォーマット機能を備えているため、実行可能であるように見えます。また、.NETでDateTimeのために実行したいと思っていました
Guillaume86

5
「。」をすべて使用すれば、非常に簡単です。序数の文字。ドイツ語の場合と同様です。 12の異なる組み合わせの単数形と複数形に加えて、3つの異なる記事の文法例。考えてみてください。ロシア語には2つ以上の語彙があり、語彙もありません。いくつかの北欧言語には15個あります。.NETでの実装を見てみたいと思いました。
Stefan Steiger 2015年

22

JesseのバージョンのStuとsamjudsonのバージョン:)

番号<1の場合、受け入れられた回答が正しくないことを示すためのユニットテストが含まれています

    /// <summary>
    /// Get the ordinal value of positive integers.
    /// </summary>
    /// <remarks>
    /// Only works for english-based cultures.
    /// Code from: http://stackoverflow.com/questions/20156/is-there-a-quick-way-to-create-ordinals-in-c/31066#31066
    /// With help: http://www.wisegeek.com/what-is-an-ordinal-number.htm
    /// </remarks>
    /// <param name="number">The number.</param>
    /// <returns>Ordinal value of positive integers, or <see cref="int.ToString"/> if less than 1.</returns>
    public static string Ordinal(this int number)
    {
        const string TH = "th";
        string s = number.ToString();

        // Negative and zero have no ordinal representation
        if (number < 1)
        {
            return s;
        }

        number %= 100;
        if ((number >= 11) && (number <= 13))
        {
            return s + TH;
        }

        switch (number % 10)
        {
            case 1: return s + "st";
            case 2: return s + "nd";
            case 3: return s + "rd";
            default: return s + TH;
        }
    }

    [Test]
    public void Ordinal_ReturnsExpectedResults()
    {
        Assert.AreEqual("-1", (1-2).Ordinal());
        Assert.AreEqual("0", 0.Ordinal());
        Assert.AreEqual("1st", 1.Ordinal());
        Assert.AreEqual("2nd", 2.Ordinal());
        Assert.AreEqual("3rd", 3.Ordinal());
        Assert.AreEqual("4th", 4.Ordinal());
        Assert.AreEqual("5th", 5.Ordinal());
        Assert.AreEqual("6th", 6.Ordinal());
        Assert.AreEqual("7th", 7.Ordinal());
        Assert.AreEqual("8th", 8.Ordinal());
        Assert.AreEqual("9th", 9.Ordinal());
        Assert.AreEqual("10th", 10.Ordinal());
        Assert.AreEqual("11th", 11.Ordinal());
        Assert.AreEqual("12th", 12.Ordinal());
        Assert.AreEqual("13th", 13.Ordinal());
        Assert.AreEqual("14th", 14.Ordinal());
        Assert.AreEqual("20th", 20.Ordinal());
        Assert.AreEqual("21st", 21.Ordinal());
        Assert.AreEqual("22nd", 22.Ordinal());
        Assert.AreEqual("23rd", 23.Ordinal());
        Assert.AreEqual("24th", 24.Ordinal());
        Assert.AreEqual("100th", 100.Ordinal());
        Assert.AreEqual("101st", 101.Ordinal());
        Assert.AreEqual("102nd", 102.Ordinal());
        Assert.AreEqual("103rd", 103.Ordinal());
        Assert.AreEqual("104th", 104.Ordinal());
        Assert.AreEqual("110th", 110.Ordinal());
        Assert.AreEqual("111th", 111.Ordinal());
        Assert.AreEqual("112th", 112.Ordinal());
        Assert.AreEqual("113th", 113.Ordinal());
        Assert.AreEqual("114th", 114.Ordinal());
        Assert.AreEqual("120th", 120.Ordinal());
        Assert.AreEqual("121st", 121.Ordinal());
        Assert.AreEqual("122nd", 122.Ordinal());
        Assert.AreEqual("123rd", 123.Ordinal());
        Assert.AreEqual("124th", 124.Ordinal());
    }

15

シンプル、クリーン、迅速

    private static string GetOrdinalSuffix(int num)
    {
        if (num.ToString().EndsWith("11")) return "th";
        if (num.ToString().EndsWith("12")) return "th";
        if (num.ToString().EndsWith("13")) return "th";
        if (num.ToString().EndsWith("1")) return "st";
        if (num.ToString().EndsWith("2")) return "nd";
        if (num.ToString().EndsWith("3")) return "rd";
        return "th";
    }

または、より良い方法として、拡張メソッドとして

public static class IntegerExtensions
{
    public static string DisplayWithSuffix(this int num)
    {
        if (num.ToString().EndsWith("11")) return num.ToString() + "th";
        if (num.ToString().EndsWith("12")) return num.ToString() + "th";
        if (num.ToString().EndsWith("13")) return num.ToString() + "th";
        if (num.ToString().EndsWith("1")) return num.ToString() + "st";
        if (num.ToString().EndsWith("2")) return num.ToString() + "nd";
        if (num.ToString().EndsWith("3")) return num.ToString() + "rd";
        return num.ToString() + "th";
    }
}

今すぐ電話できます

int a = 1;
a.DisplayWithSuffix(); 

または直接

1.DisplayWithSuffix();

14

自分でロールバックする必要があります。私の頭の上から:

public static string Ordinal(this int number)
{
  var work = number.ToString();
  if ((number % 100) == 11 || (number % 100) == 12 || (number % 100) == 13)
    return work + "th";
  switch (number % 10)
  {
    case 1: work += "st"; break;
    case 2: work += "nd"; break;
    case 3: work += "rd"; break;
    default: work += "th"; break;
  }
  return work;
}

その後、行うことができます

Console.WriteLine(432.Ordinal());

2013年11月12日の例外を編集。私は頭の上から言った:-)

1011用に編集-他の人はすでにこれを修正していますが、他の人がこの間違ったバージョンを取得しないようにしたいだけです。


12

Stusamjudsonの両方のソリューションの要素が好きで、それらを組み合わせて、私が使用できるコンボだと思うものにまとめました。

    public static string Ordinal(this int number)
    {
        const string TH = "th";
        var s = number.ToString();

        number %= 100;

        if ((number >= 11) && (number <= 13))
        {
            return s + TH;
        }

        switch (number % 10)
        {
            case 1:
                return s + "st";
            case 2:
                return s + "nd";
            case 3:
                return s + "rd";
            default:
                return s + TH;
        }
    }

1
"th"に定数を使用する理由は何ですか?
nickf 2008

コードで2回使用されているためです。繰り返してはならない古き良き知恵を利用するだけです:)この場合、.NETランタイムは文字列のコピーを1つだけ作成し、コードに「th」が2つあると、2つの文字列が作成されます。メモリで参照されます。
Jesse C. Slicer

25
また、THの値が変化する場合は、設定されます。
Eclipse

7
@Jesse -あなたは私の1を得るが、私が見る、.NETハンドル文字列をこのように考えていないyoda.arachsys.com/csharp/strings.html#interningの私の読書は「目」リテラルをそれぞれ参照され、同じメモリのビットを参照します。しかし、私はDRYに同意します:)
si618 2009年

4
このような重複を削除すると、読みやすさを損なうだけで、「なぜTHなのか」という混乱が生じます。私は、DRYが「コストを問わずすべての重複を削除する」と解釈されるべきではないと思います。
SeeNoWeevil 2013年

8

これについてはまだベンチマークしていませんが、条件付きのcaseステートメントをすべて回避することで、パフォーマンスを向上させることができます。

これはjavaですが、C#への移植は簡単です。

public class NumberUtil {
  final static String[] ORDINAL_SUFFIXES = {
    "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
  };

  public static String ordinalSuffix(int value) {
    int n = Math.abs(value);
    int lastTwoDigits = n % 100;
    int lastDigit = n % 10;
    int index = (lastTwoDigits >= 11 && lastTwoDigits <= 13) ? 0 : lastDigit;
    return ORDINAL_SUFFIXES[index];
  }

  public static String toOrdinal(int n) {
    return new StringBuffer().append(n).append(ordinalSuffix(n)).toString();
  }
}

条件付きの数を減らし、配列ルックアップを使用すると、タイトなループで多数の序数を生成する場合にパフォーマンスが向上することに注意してください。ただし、これはケースステートメントソリューションほど読みにくいことも認めます。


これをC#でベンチマークして申し訳ありませんが、バージョンはsi618のソリューションよりも高速ではありません。
GY_

この回答を確認してくださいstackoverflow.com/a/58378465/2583579いくつかのベンチマークのために
ダンDohotaru

3

ライアンのソリューションに似ていますが、さらに基本的なのは、単純な配列を使用し、日付を使用して正しい序数を検索することです。

private string[] ordinals = new string[] {"","st","nd","rd","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","st","nd","rd","th","th","th","th","th","th","th","st" };
DateTime D = DateTime.Now;
String date = "Today's day is: "+ D.Day.ToString() + ordinals[D.Day];

必要はありませんでしたが、多言語サポートが必要な場合は、多次元配列を使用できると思います。

私がユニの日から覚えていることから、この方法はサーバーからの最小限の労力を必要とします。


2

私はこの拡張クラスを使用します:

public static class Int32Extensions
{
    public static string ToOrdinal(this int i)
    {
        return (i + "th")
            .Replace("1th", "1st")
            .Replace("2th", "2nd")
            .Replace("3th", "3rd");
    }
}

11日、12日、13
Kcoder

2

samjudsonの回答の「冗長性の少ない」バージョンを要求しました...

public static string AddOrdinal(int number)
{
    if (number <= 0) return number.ToString();

    string GetIndicator(int num)
    {
        switch (num % 100)
        {
            case 11:
            case 12:
            case 13:
                return "th";
        }

        switch (num % 10)
        {
            case 1:
                return "st";
            case 2:
                return "nd";
            case 3:
                return "rd";
            default:
                return "th";
        }
    }

    return number + GetIndicator(number);
}

2
「GetIndicator」をとして公開public staticし、よりニーモニックな名前に変更します(「OrdinalSuffix」など)。発信者は、さまざまな形式(つまり、コンマ)の数値部分が必要な場合があります。
トム、

2
        private static string GetOrd(int num) => $"{num}{(!(Range(11, 3).Any(n => n == num % 100) ^ Range(1, 3).All(n => n != num % 10)) ? new[] { "ˢᵗ", "ⁿᵈ", "ʳᵈ" }[num % 10 - 1] : "ᵗʰ")}";

誰かが1つのライナーを探しているなら:p


1
public static string OrdinalSuffix(int ordinal)
{
    //Because negatives won't work with modular division as expected:
    var abs = Math.Abs(ordinal); 

    var lastdigit = abs % 10; 

    return 
        //Catch 60% of cases (to infinity) in the first conditional:
        lastdigit > 3 || lastdigit == 0 || (abs % 100) - lastdigit == 10 ? "th" 
            : lastdigit == 1 ? "st" 
            : lastdigit == 2 ? "nd" 
            : "rd";
}

1

編集:YM_Industriesがコメントで指摘しているように、samjudsonの回答は1000を超える数値で機能します。nickfのコメントはなくなったようで、私が見た問題が何であったか思い出せません。比較のタイミングについては、この回答をここに残しました。

nickfがコメントで指摘したように、これらの多くは999を超える数では機能しません(編集:現在欠落しています)。

これはsamjudson承認された回答の修正バージョンに基づくバージョンです。

public static String GetOrdinal(int i)
{
    String res = "";

    if (i > 0)
    {
        int j = (i - ((i / 100) * 100));

        if ((j == 11) || (j == 12) || (j == 13))
            res = "th";
        else
        {
            int k = i % 10;

            if (k == 1)
                res = "st";
            else if (k == 2)
                res = "nd";
            else if (k == 3)
                res = "rd";
            else
                res = "th";
        }
    }

    return i.ToString() + res;
}

また、文字列操作を使用したShahzad Qureshi回答は正常に機能しますが、パフォーマンスが低下します。これらの多くを生成するために、LINQPadのサンプルプログラムでは、文字列バージョンをこの整数の文字列よりも6〜7倍遅くしています(ただし、気付くにはたくさん生成する必要があります)。

LINQPadの例:

void Main()
{
    "Examples:".Dump();

    foreach(int i in new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 113, 122, 201, 202, 211, 212, 2013, 1000003, 10000013 })
        Stuff.GetOrdinal(i).Dump();

    String s;

    System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();

    for(int iter = 0; iter < 100000; iter++)
        foreach(int i in new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 113, 122, 201, 202, 211, 212, 2013, 1000003, 1000013 })
            s = Stuff.GetOrdinal(i);

    "Integer manipulation".Dump();
    sw.Elapsed.Dump();

    sw.Restart();

    for(int iter = 0; iter < 100000; iter++)
        foreach(int i in new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 113, 122, 201, 202, 211, 212, 2013, 1000003, 1000013 })
            s = (i.ToString() + Stuff.GetOrdinalSuffix(i));

    "String manipulation".Dump();
    sw.Elapsed.Dump();
}

public class Stuff
{
        // Use integer manipulation
        public static String GetOrdinal(int i)
        {
                String res = "";

                if (i > 0)
                {
                        int j = (i - ((i / 100) * 100));

                        if ((j == 11) || (j == 12) || (j == 13))
                                res = "th";
                        else
                        {
                                int k = i % 10;

                                if (k == 1)
                                        res = "st";
                                else if (k == 2)
                                        res = "nd";
                                else if (k == 3)
                                        res = "rd";
                                else
                                        res = "th";
                        }
                }

                return i.ToString() + res;
        }

        // Use string manipulation
        public static string GetOrdinalSuffix(int num)
        {
                if (num.ToString().EndsWith("11")) return "th";
                if (num.ToString().EndsWith("12")) return "th";
                if (num.ToString().EndsWith("13")) return "th";
                if (num.ToString().EndsWith("1")) return "st";
                if (num.ToString().EndsWith("2")) return "nd";
                if (num.ToString().EndsWith("3")) return "rd";
                return "th";
        }
}

@nickfのコメントが見つかりません。samjudsonの回答の何が問題になっていますか?それはあなたのよりもはるかに読みやすく、1000を超える数値をうまく処理するように思えます。
Joshua Walsh

1
公正なコメントです。テストセットを実行しただけで、問題は見つかりませんでした。サムの答えにも変更が加えられていないようで、私が怒っているのは想像できません。私はそれを反映するように私の回答を編集しました。
Whelkaholism

1
ははは、そういう瞬間がありますね。私たちは古いコードを振り返り、「なぜ私はなぜこれを書いたのですか?」
Joshua Walsh、

1

他の回答に基づいて:

public static string Ordinal(int n)
{   
    int     r = n % 100,     m = n % 10;

    return (r<4 || r>20) && (m>0 && m<4) ? n+"  stndrd".Substring(m*2,2) : n+"th";                                              
}

3
1st PLACE:最も不必要な不可解な答え。「不必要」:読みやすさのコストに見合わないコードサイズ/パフォーマンスの利点。「不可解」:「素人」要件にマップするために必要な重要な翻訳。
トム

0

FWIW、MS-SQLの場合、この式が機能します。最初のWHEN(WHEN num % 100 IN (11, 12, 13) THEN 'th')をリストの最初のWHEN()のままにします。これは、他の前に試行されることに依存しているためです。

CASE
  WHEN num % 100 IN (11, 12, 13) THEN 'th' -- must be tried first
  WHEN num % 10 = 1 THEN 'st'
  WHEN num % 10 = 2 THEN 'nd'
  WHEN num % 10 = 3 THEN 'rd'
  ELSE 'th'
END AS Ordinal

Excelの場合:

=MID("thstndrdth",MIN(9,2*RIGHT(A1)*(MOD(A1-11,100)>2)+1),2)

(MOD(A1-11,100)>2)は、末尾が11,12,13(FALSE = 0)以外のすべての数値でTRUE(1)です。つまり2 * RIGHT(A1) * (MOD(A1-11,100)>2) +1)、11/12/13の場合は1になります。それ以外の場合は、
1は3に評価されます
2から5、3
から7は
その他に評価されます:9-
そして、必要な2文字が"thstndrdth"その位置から選択されます。

あなたが本当にそれをかなり直接SQLに変換したいのであれば、これは私にとっていくつかのテスト値のためにうまくいきました:

DECLARE @n as int
SET @n=13
SELECT SubString(  'thstndrdth'
                 , (SELECT MIN(value) FROM
                     (SELECT 9 as value UNION
                      SELECT 1+ (2* (ABS(@n) % 10)  *  CASE WHEN ((ABS(@n)+89) % 100)>2 THEN 1 ELSE 0 END)
                     ) AS Mins
                   )
                 , 2
                )

0

これはの実装でdartあり、言語に応じて変更できます。

String getOrdinalSuffix(int num){
    if (num.toString().endsWith("11")) return "th";
    if (num.toString().endsWith("12")) return "th";
    if (num.toString().endsWith("13")) return "th";
    if (num.toString().endsWith("1")) return "st";
    if (num.toString().endsWith("2")) return "nd";
    if (num.toString().endsWith("3")) return "rd";
    return "th";
}

0

ここには良い答えがたくさんありますが、今度はパターンマッチングに基づいた別の答えの余地があると思います。

    public static string Ordinals1(this int number)
    {
        switch (number)
        {
            case int p when p % 100 == 11:
            case int q when q % 100 == 12:
            case int r when r % 100 == 13:
                return $"{number}th";
            case int p when p % 10 == 1:
                return $"{number}st";
            case int p when p % 10 == 2:
                return $"{number}nd";
            case int p when p % 10 == 3:
                return $"{number}rd";
            default:
                return $"{number}th";
        }
    }

そして、このソリューションは何が特別なのですか?他のさまざまなソリューションにパフォーマンスの考慮事項を追加しているという事実にすぎません

率直に言って、この特定のシナリオ(数百万の序数が本当に必要なシナリオ)でパフォーマンスが本当に重要であるかどうかは疑問ですが、少なくとも考慮に入れられるいくつかの比較が浮かび上がります...

参考のために100万個のアイテム(当然、マシンの仕様によってミレージは異なる場合があります)

パターンマッチングと除算(この答え)

約622ミリ秒

パターンマッチングと文字列(この答え)

〜1967 ms

2つのスイッチとディビジョン(受け入れられた回答)

〜637 ms

1つのスイッチと分割(別の答え)

〜725 ms

void Main()
{
    var timer = new Stopwatch();
    var numbers = Enumerable.Range(1, 1000000).ToList();

    // 1
    timer.Reset();
    timer.Start();
    var results1 = numbers.Select(p => p.Ordinals1()).ToList();
    timer.Stop();
    timer.Elapsed.TotalMilliseconds.Dump("with pattern matching and divisions");

    // 2
    timer.Reset();
    timer.Start();
    var results2 = numbers.Select(p => p.Ordinals2()).ToList();
    timer.Stop();
    timer.Elapsed.TotalMilliseconds.Dump("with pattern matching and strings");

    // 3
    timer.Reset();
    timer.Start();
    var results3 = numbers.Select(p => p.Ordinals3()).ToList();
    timer.Stop();
    timer.Elapsed.TotalMilliseconds.Dump("with two switches and divisons");

    // 4
    timer.Reset();
    timer.Start();
    var results4 = numbers.Select(p => p.Ordinals4()).ToList();
    timer.Stop();
    timer.Elapsed.TotalMilliseconds.Dump("with one switche and divisons");
}

public static class Extensions
{
    public static string Ordinals1(this int number)
    {
        switch (number)
        {
            case int p when p % 100 == 11:
            case int q when q % 100 == 12:
            case int r when r % 100 == 13:
                return $"{number}th";
            case int p when p % 10 == 1:
                return $"{number}st";
            case int p when p % 10 == 2:
                return $"{number}nd";
            case int p when p % 10 == 3:
                return $"{number}rd";
            default:
                return $"{number}th";
        }
    }

    public static string Ordinals2(this int number)
    {
        var text = number.ToString();
        switch (text)
        {
            case string p when p.EndsWith("11"):
                return $"{number}th";
            case string p when p.EndsWith("12"):
                return $"{number}th";
            case string p when p.EndsWith("13"):
                return $"{number}th";
            case string p when p.EndsWith("1"):
                return $"{number}st";
            case string p when p.EndsWith("2"):
                return $"{number}nd";
            case string p when p.EndsWith("3"):
                return $"{number}rd";
            default:
                return $"{number}th";
        }
    }

    public static string Ordinals3(this int number)
    {
        switch (number % 100)
        {
            case 11:
            case 12:
            case 13:
                return $"{number}th";
        }

        switch (number % 10)
        {
            case 1:
                return $"{number}st";
            case 2:
                return $"{number}nd";
            case 3:
                return $"{number}rd";
            default:
                return $"{number}th";
        }
    }

    public static string Ordinals4(this int number)
    {
        var ones = number % 10;
        var tens = Math.Floor(number / 10f) % 10;
        if (tens == 1)
        {
            return $"{number}th";
        }

        switch (ones)
        {
            case 1:
                return $"{number}th";
            case 2:
                return $"{number}nd";
            case 3:
                return $"{number}rd";
            default:
                return $"{number}th";
        }
    }
}

0

別のワンライナーですが、正規表現の結果を配列にインデックスするだけで比較は行われません。

public static string GetOrdinalSuffix(int input)
{
    return new []{"th", "st", "nd", "rd"}[Convert.ToInt32("0" + Regex.Match(input.ToString(), "(?<!1)[1-3]$").Value)];
}

PowerShellバージョンはさらに短縮できます。

function ord($num) { return ('th','st','nd','rd')[[int]($num -match '(?<!1)[1-3]$') * $matches[0]] }

0

別の1ライナー。

public static string Ordinal(this int n)
{    
 return n + (new [] {"st","nd","rd" }.ElementAtOrDefault((((n + 90) % 100 - 10) % 10 - 1)) ?? "th");
}

-2

以下はDateTime Extensionクラスです。コピー、貼り付け、お楽しみください

public static class DateTimeExtensions {

    public static string ToStringWithOrdinal(this DateTime d)
    {
        var result = "";
        bool bReturn = false;            

        switch (d.Day % 100)
        {
            case 11:
            case 12:
            case 13:
                result = d.ToString("dd'th' MMMM yyyy");
                bReturn = true;
                break;
        }

        if (!bReturn)
        {
            switch (d.Day % 10)
            {
                case 1:
                    result = d.ToString("dd'st' MMMM yyyy");
                    break;
                case 2:
                    result = d.ToString("dd'nd' MMMM yyyy");
                    break;
                case 3:
                    result = d.ToString("dd'rd' MMMM yyyy");
                    break;
                default:
                    result = d.ToString("dd'th' MMMM yyyy");
                    break;
            }

        }

        if (result.StartsWith("0")) result = result.Substring(1);
        return result;
    }
}

結果:

2014年10月9日


あなたは複製しています:a)日付フォーマット文字列(X5)およびb)メソッドの残りの部分(可能性のあるユースケースが発生した場合(まだ発生していない場合))、月の日以外に通常のサフィックスが必要です目的、または異なる日付フォーマット文字列を使用した月間)。Ian Warburtonの2017年4月6日16:32の回答(stackoverflow.com/questions/20156/…)から公開することを提案した「OrdinalSuffix」メソッドを使用します。
トム

-3

他のすべての提案に基づいて使用した別の代替方法ですが、特別な大文字小文字の区別は必要ありません。

    public static string DateSuffix(int day)
    {
        if (day == 11 | day == 12 | day == 13) return "th";
        Math.DivRem(day, 10, out day);
        switch (day)
        {
            case 1:
                return "st";
            case 2:
                return "nd";
            case 3:
                return "rd";
            default:
                return "th";
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.