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
How to Detect If I'm Running in Mono-Service
Mono High Resolution Timer (On Linux)
Command (.4Gl) Executed with Ssh.Net Sshclient.Runcommand Fails with "No Such File or Directory"
Byte Array to Image Conversion
C# Okay with Comparing Value Types to Null
How to Tell a Lambda Function to Capture a Copy Instead of a Reference in C#
C# List of Objects, How to Get the Sum of a Property
ASP.NET MVC: No Parameterless Constructor Defined for This Object
What's the Best Way of Implementing a Thread-Safe Dictionary
How to Read an Attribute on a Class at Runtime
How to Return Null from a Generic Method in C#
Why Can't I Use the 'Await' Operator Within the Body of a Lock Statement