How to Create Ordinals in C#

Is there an easy way to create ordinals in C#?

This page gives you a complete listing of all custom numerical formatting rules:

Custom numeric format strings

As you can see, there is nothing in there about ordinals, so it can't be done using String.Format. However its not really that hard to write a function to do it.

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";
}
}

Update: Technically Ordinals don't exist for <= 0, so I've updated the code above. Also removed the redundant ToString() methods.

Also note, this is not internationalized. I've no idea what ordinals look like in other languages.

Is there an easy way in .NET to get st , nd , rd and th endings for numbers?

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

How can i format 07/03/2012 to March 7th,2012 in c#

You can create your own custom format provider to do this:

public class MyCustomDateProvider: IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;

return null;
}

public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!(arg is DateTime)) throw new NotSupportedException();

var dt = (DateTime) arg;

string suffix;

if (new[] {11, 12, 13}.Contains(dt.Day))
{
suffix = "th";
}
else if (dt.Day % 10 == 1)
{
suffix = "st";
}
else if (dt.Day % 10 == 2)
{
suffix = "nd";
}
else if (dt.Day % 10 == 3)
{
suffix = "rd";
}
else
{
suffix = "th";
}

return string.Format("{0:MMMM} {1}{2}, {0:yyyy}", arg, dt.Day, suffix);
}
}

This can then be called like this:

var formattedDate = string.Format(new MyCustomDateProvider(), "{0}", date);

Resulting in (for example):

March 3rd, 2012

DataReader - hardcode ordinals?

It is possible to argue both sides in this situation. As already pointed out by others, using the name is more readable and will not break if someone changes the order of columns in the underlying database. But one might also argue the case that using an ordinal has the advantage of not breaking if someone changes the column name in the underlying database. I prefer the former argument, though, and think the readability argument for column names trumps the second argument in general. And an additional argument for names is that it is that it can “self-detect” errors. If someone does change a field name, then the code has a better chance of breaking rather than having the subtle bug of appearing to work while it reads the wrong field.

It seems obvious but maybe it is worth mentioning a usage case that has both the self-detecting error and the performance of ordinals. If you specify the SELECT list explicitly in the SQL, then using ordinals won’t be a problem because the statement in the code guarantees the order:

SELECT name, address, phone from mytable

In this case, it would be fairly safe to use ordinals to access the data. It doesn’t matter if someone moves fields around in the table. And if someone changes a name, then the SQL statement produce an error when it runs.

And one final point. I just ran a test on a provider I helped write. The test read 1 million rows and accessed the “lastname” field on each record (compared against a value). The usage of rdr[“lastname”] took 3301 milliseconds to process while rdr.GetString(1) took 2640 milliseconds (approximately a 25% speedup). In this particular provider, the lookup of the name uses a sorted lookup to translate the name to ordinal.

Ordinal Date Format C#

Hmm, I am not sure if there is a more direct way, but this should work

new DateTime(year, 1, 1).AddDays(day - 1);

Get the ordinal position while creating selected Item in a LINQ expression

Use the overload of Select which provides the index as well as the value. In this case I'd use AsEnumerable to get out of the database context, which isn't really where you want to be doing this work:

string[] alphaOrdinals = { "A", "B", "C", "D", "E" };
var query = dataContext.Cars
.AsEnumerable()
.Select((car, index) => new InventoryItem {
Name = car.Name,
Price = car.Price,
UIElement = string.Format("Car {0} {1}",
car.Id,
alphaOrdinals[index])
}).ToList();

(You can change alphaOrdinals to a string without any other change to the code, btw.)

toTitleCase to ignore ordinals in C#

string input =  System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello there, this is the 1st");
string result = System.Text.RegularExpressions.Regex.Replace(input, "([0-9]st)|([0-9]th)|([0-9]rd)|([0-9]nd)", new System.Text.RegularExpressions.MatchEvaluator((m) =>
{
return m.Captures[0].Value.ToLower();
}), System.Text.RegularExpressions.RegexOptions.IgnoreCase);


Related Topics



Leave a reply



Submit