String.Format - how it works and how to implement custom formatstrings
String.Format
matches each of the tokens inside the string ({0}
etc) against the corresponding object: https://learn.microsoft.com/en-us/dotnet/api/system.string.format#overloads
A format string is optionally provided:
{ index[,alignment][ : formatString] }
If formatString
is provided, the corresponding object must implement IFormattable and specifically the ToString
method that accepts formatString
and returns the corresponding formatted string: https://learn.microsoft.com/en-us/dotnet/api/system.iformattable.tostring
An IFormatProvider
may also be used to capture basic formatting standards/defaults etc. Examples here and here.
So the answers to your questions in order:
It uses the
IFormattable
interface'sToString()
method on theDateTime
object and passes that theMM/dd/yyyy
format string. It is that implementation which returns the correct string.Any object that implement
IFormattable
supports this feature. You can even write your own!Yes, see above.
Custom string formatter in C#
You can make a custom formatter, something like:
public class MyFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string fmt, object arg, IFormatProvider formatProvider)
{
if(arg == null) return string.Empty;
if(fmt == "lcase")
return arg.ToString().ToLower();
else if(fmt == "ucase")
return arg.ToString().ToUpper();
else if(fmt == "nospace")
return arg.ToString().Replace(" ", "");
// Use this if you want to handle default formatting also
else if (arg is IFormattable)
return ((IFormattable)arg).ToString(fmt, CultureInfo.CurrentCulture);
return arg.ToString();
}
}
Then use it like:
string.Format(new MyFormatter(),
"{0:lcase}, {0:ucase}, {0:nospace}",
"My Test String")
This should return:
my test string, MY TEST STRING, MyTestString
Create custom format strings for a new .NET type, for use in String.Format?
There is the IFormattable interface...
class MyObject : IFormattable
{
public string ToString(string format, IFormatProvider formatProvider)
{
throw new NotImplementedException();
}
}
Probably you only have to implement it.
The IFormattable interface converts an object to its string representation based on a format string and a format provider.
Try with
class Foo : IFormattable
{
public string ToString(string format, IFormatProvider formatProvider)
{
return string.Format("Foo formatted as {0}", format != null ? format : "(null)");
}
}
Console.WriteLine("{0}, {0:xxx}", new Foo());
The {0}
is passed as null
, while the {0:xxx}
is passed as xxx
How to provide custom formatting from format string?
You would normally use custom string formatting for that (see PEP 3101). For your case, you could have something like this:
import string
class MyFormatter(string.Formatter):
def format_field(self, value, format_spec):
if isinstance(value, str):
if format_spec.endswith('u'):
value = value.upper()
format_spec = format_spec[:-1]
elif format_spec.endswith('l'):
value = value.lower()
format_spec = format_spec[:-1]
return super(MyFormatter, self).format(value, format_spec)
fmt = MyFormatter()
print(fmt.format('uppercase: {s:u}, lowercase: {s:l}', s='abc'))
# uppercase: ABC, lowercase: abc
How to implement MyMethod() with Format(blah {0}, someValue) signature like string.format
It's pretty trivial, but there are less trivial uses of params:
static string MyMethod( string format, params object[] paramList )
{
return string.Format(format, paramList);
}
How to format strings in Java
In addition to String.format, also take a look java.text.MessageFormat
. The format less terse and a bit closer to the C# example you've provided and you can use it for parsing as well.
For example:
int someNumber = 42;
String someString = "foobar";
Object[] args = {new Long(someNumber), someString};
MessageFormat fmt = new MessageFormat("String is \"{1}\", number is {0}.");
System.out.println(fmt.format(args));
A nicer example takes advantage of the varargs and autoboxing improvements in Java 1.5 and turns the above into a one-liner:
MessageFormat.format("String is \"{1}\", number is {0}.", 42, "foobar");
MessageFormat
is a little bit nicer for doing i18nized plurals with the choice modifier. To specify a message that correctly uses the singular form when a variable is 1 and plural otherwise, you can do something like this:
String formatString = "there were {0} {0,choice,0#objects|1#object|1<objects}";
MessageFormat fmt = new MessageFormat(formatString);
fmt.format(new Object[] { new Long(numberOfObjects) });
How to use String.format() in Java?
It works same as printf() of C.
%s for String
%d for int
%f for float
ahead
String.format("%02d", 8)
OUTPUT: 08
String.format("%02d", 10)
OUTPUT: 10
String.format("%04d", 10)
OUTPUT: 0010
so basically, it will pad number of 0's ahead of the expression, variable or primitive type given as the second argument, the 0's will be padded in such a way that all digits satisfies the first argument of format method of String API.
How to disambiguate between the 'd' Standard and Custom format strings for .Net DateTime?
To distinguish between a custom and standard format when the format is only a single character, use the %
symbol. For example: {0:d}
gives the standard date format, but {0:%d}
gives just the day of the month. See the MSDN docs for more details.
So, you could do this:
String.Format("{0,2:%d} {0:MMM HH:mm:ss}", ...
However, consider that you could also just specify the length of the entire string:
String.Format("{0,15:d MMM HH:mm:ss}", ...
Of course, this assumes that MMM
will always be three characters long. That is true for English (as .NET uses "Sep" instead of "Sept"), but isn't guaranteed for all languages and locales.
Also note that you should use HH
for 24 hour time. hh
gives 12 hour time, but is meaningless without using tt
to indicate the meridem designation (am/pm).
Combine custom numeric format string with hex format string
The following format string is ALMOST correct:
string format = "0x{0:X8}";
Console.WriteLine(format, 10);
Console.WriteLine(format, -10);
Console.WriteLine(format, 0);
gives:
0x0000000A
0xFFFFFFF6
0x00000000
I'm still trying to work the '' for 0.
EDIT: I am having the same issue, with the X8's becoming literals only when the format string has the seperator ';' in use. I'm just going to poke around in the .NET source and see what I can see.
EDIT 2: The follow extension method will return a string with the correct formatting, both for +'ves, -'ves and 0. The parameter length is the amount of characters required in the hex string (excluding the '0x' on the front).
public static string ToHexString(this int source, int length)
{
return (source != 0) ? string.Format("0x{0:X" + length.ToString() + "}",source) : string.Empty;
}
Related Topics
How to Know What Image Format I Get from a Stream
Extract Thumbnail for Any File in Windows
.Net (3.5) Formats Times Using Dots Instead of Colons as Timeseparator for It-It Culture
The Bare Minimum Needed to Write a Msmq Sample Application
Newtonsoft Inline Formatting for Subelement While Serializing
Is Idisposable.Dispose() Called Automatically
Button in a Column, Getting the Row from Which It Came on the Click Event Handler
How to Create a File and Any Folders, If the Folders Don't Exist
How to Validate Signature of Jwt from Jwks Without X5C
How to Know the Selected Checkboxes from Within the Httppost Create Action Method
How to Redirect to Index from Another Controller
Print Rdlc Report Without Showing Reportviewer Control
Total Number of Items Defined in an Enum
Dynamically Updating Tabcontrol Content at Runtime