views:

2740

answers:

8

Hi,

I am wondering if there is a method or format string I'm missing in .NET to convert the following:

   1 to 1st
   2 to 2nd
   3 to 3rd
   4 to 4th
  11 to 11th
 101 to 101st
 111 to 111th

This link has a bad example of the basic principle involved in writing your own function, but I am more curious if there is an inbuilt capacity I'm missing.

Solution

Scott Hanselman's answer is the accepted one because it answers the question directly.

For a solution however, see this great answer.

+14  A: 

No, there is no inbuilt capability in the .NET Base Class Library.

Scott Hanselman
+41  A: 

It's a function which is a lot simpler than you think. Though there might be a .NET function already in existence for this, the following function (written in PHP) does the job. It shouldn't be too hard to port it over.

function ordinal($num) {
    $ones = $num % 10;
    $tens = floor($num / 10) % 10;
    if ($tens == 1) {
        $suff = "th";
    } else {
        switch ($ones) {
            case 1 : $suff = "st"; break;
            case 2 : $suff = "nd"; break;
            case 3 : $suff = "rd"; break;
            default : $suff = "th";
        }
    }
    return $num . $suff;
}
nickf
What about localization?
macbirdie
Localization will mean that you have to create separate functions for each language. In german, you could just append "ter", but "1ter" "2ter" "3ter" looks really bad even though it's grammatically correct. In french, it's a bit better, but there is no universal way for every language.
Michael Stum
@Michael Stum: I'm not too familiar with all the international ordinal formats but would a string.Format(resString, number) suffice? Or do some languages not combine numbers with ordinal (pre/suff)ixes?
Graphain
+6  A: 

This has already been covered but I'm unsure how to link to it. Here is the code snippit:

 public static string Ordinal(this int number)
 {
  var ones = number % 10;
  var tens = Math.Floor (number / 10f) % 10;
  if (tens == 1)
  {
   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";
  }
 }

FYI: This is as an extension method. If your .NET version is less than 3.5 just remove the this keyword

[EDIT]: Thanks for pointing that it was incorrect, that's what you get for copy / pasting code :)

marshall
Doesn't work.1011 % 10 == 1.1011st is incorrect.
Graphain
+1 for extension method
Even Mien
I like how you declare the ones variable and never use it.
John Gietzen
A: 

I think the ordinal suffix is hard to get... you basically have to write a function that uses a switch to test the numbers and add the suffix.

There's no reason for a language to provide this internally, especially when it's locale specific.

You can do a bit better than that link when it comes to the amount of code to write, but you have to code a function for this...

Hugh Buchanan
Given all the currency localisation strings etc. it seems a little stretch to add ordinal suffix.
Graphain
+13  A: 

@nickf: Here is the PHP function in C#:

public static string Ordinal(int number)
{
 string suffix = String.Empty;

 int ones = number % 10;
 int tens = (int)Math.Floor(number / 10M) % 10;

 if (tens == 1)
 {
  suffix = "th";
 }
 else
 {
  switch (ones)
  {
   case 1:
    suffix = "st";
    break;

   case 2:
    suffix = "nd";
    break;

   case 3:
    suffix = "rd";
    break;

   default:
    suffix = "th";
    break;
  }
 }
 return String.Format("{0}{1}", number, suffix);
}
Scott Dorman
Ha thanks, just about to post the code I wrote out. Yours beats mine anyway with the String.Format bit I think.
Graphain
+3  A: 

This has already been asked, and answered:

Ordinals in C#

Portman
A: 

else if (choice=='q') {qtr++;

                   switch (qtr)
                  {  case(2): strcpy(qtrs,"nd");break;
                     case(3): {strcpy(qtrs,"rd");
                               cout<<"End of First Half!!!";
                               cout<<" hteam "<<"["<<hteam<<"] "<<hs;
                               cout<<" vteam "<<" ["<<vteam;
                               cout<<"] ";
                               cout<<vs;dwn=1;yd=10;

                               if (beginp=='H') team='V';
                               else             team='H';
                               break;
                               }
                   case(4): strcpy(qtrs,"th");break;
+2  A: 

Here's a Microsoft SQL Server Function version:

CREATE FUNCTION [Internal].[GetNumberAsOrdinalString]
(
    @num int
)
RETURNS nvarchar(max)
AS
BEGIN

    DECLARE @Suffix nvarchar(2);
    DECLARE @Ones int;  
    DECLARE @Tens int;

    SET @Ones = @num % 10;
    SET @Tens = FLOOR(@num / 10) % 10;

    IF @Tens = 1
    BEGIN
        SET @Suffix = 'th';
    END
    ELSE
    BEGIN

    SET @Suffix = 
        CASE @Ones
            WHEN 1 THEN 'st'
            WHEN 2 THEN 'nd'
            WHEN 3 THEN 'rd'
            ELSE 'th'
        END
    END

    RETURN CONVERT(nvarchar(max), @num) + @Suffix;
END
locster
I just wrote that function almost verbatim! Differences: master db, cast instead of convert, and I use slightly different indenting. Great minds, I guess...
John Gietzen