It's because it thinks it's a standard format string instead of a custom one, due to being a single character.
A better way of fixing this is to use %
:
string text = DateTime.Now.ToString("%h");
From the docs on custom format strings:
A custom date and time format string
consists of two or more characters.
Date and time formatting methods
interpret any single-character string
as a standard date and time format
string. If they do not recognize the
character as a valid format specifier,
they throw a FormatException. For
example, a format string that consists
only of the specifier "h" is
interpreted as a standard date and
time format string. However, in this
particular case, an exception is
thrown because there is no "h"
standard date and timeformat
specifier.
To use any of the custom date and time
format specifiers as the only
specifier in a format string (that is,
to use the "d", "f", "F", "g", "h",
"H", "K", "m", "M", "s", "t", "y",
"z", ":", or "/" custom format
specifier by itself), include a space
before or after the specifier, or
include a percent ("%") format
specifier before the single custom
date and time specifier.
For example, "%h" is interpreted as a
custom date and time format string
that displays the hour represented by
the current date and time value. You
can also use the " h" or "h " format
string, although this includes a space
in the result string along with the
hour. The following example
illustrates these three format
strings.