String.Format - How It Works and How to Implement Custom Formatstrings

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:

  1. It uses the IFormattable interface's ToString() method on the DateTime object and passes that the MM/dd/yyyy format string. It is that implementation which returns the correct string.

  2. Any object that implement IFormattable supports this feature. You can even write your own!

  3. 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



Leave a reply



Submit