# Using \@ifnextchar to define a macro for “ante meridiem” time

I want to create a macro for times of days, as follows:

\newcommand{\pmtime}{a.m.\xspace}


The problem is that LaTeX thinks that the last period in a.m. denotes the end of a sentence, hence the space produced by \xspace is too large.

\newcommand{\amtime}{a.m.\ }


The above is not helpful either, since a regular size space is now added, even when the macro does in fact occur at the end of a sentence.

I read about \@ifnextchar and tried the following:

\newcommand{\amtime}{a.m.\@ifnextchar.{}{\ }}


This expands to a.m.ifnextchar. in the text (in this case the macro is not followed by a period.

-

Because the letters a and m are lowercase, TeX does not think a.m. is an abbreviation. \@ afterwards resets the space factor and TeX does not insert a larger space (see egreg's comment).

\@ifnextchar has @ ("at") in its name, thus the pair \makeatletter and \makeatother should be used (unless it is used in a package or class file). Then @ has the catcode letter and can be part of a command name (see Werner's comment).

\@ifnextchar has the side effect of removing a following spaces, therefore the example below uses \ltx@ifnextchar@nospace of package ltxcmds that keeps a following space intact. As \@ifnextchar also \ltx@ifnextchar@nospace has three arguments, the token that is looked for (here the dot). If a dot is following, then \@gobble removes the dot to avoid to consecutive dots. \xspace is only needed for the case, that the next token is not a dot (the third argument for \ltx@ifnextchar@nospace).

\documentclass{article}
\usepackage{xspace}
\usepackage{ltxcmds}[2011/04/14]
\makeatletter
\newcommand{\amtime}{%
a.m.\@%
\ltx@ifnextchar@nospace.\@gobble\xspace
}
\newcommand{\pmtime}{%
p.m.\@%
\ltx@ifnextchar@nospace.\@gobble\xspace
}
\makeatother

\begin{document}
7\amtime, 8\amtime and 9\amtime.
\end{document}


-

The \@ifnextchar business is already taken care of by \xspace, if you use it. You just need to announce TeX that the period is not ending a sentence and the command \@ is just for that:

\usepackage{xspace}
\newcommand{\amtime}{\,a.m.\@\xspace}


will have the correct spacing. Notice \, to slightly detach "a.m." from the number preceding it (and this space will never be used for a line break).

However, I usually advice against \xspace: it's really not so difficult to remember writing \amtime{} in cases when a space is needed after it.

Why don't you try with

\newcommand{\amtime}{\,\textsc{am}}


that avoids periods?

-

Your use of \@ and \@ifnextchar unfortunately didn't throw an error, since \@ is a valid control sequence. The following is probably what you wanted to achieve with your use of \@ifnextchar:

\documentclass{article}
\usepackage{xspace}% http://ctan.org/pkg/xspace
\makeatletter
\newcommand{\amtime}{a.m.\@ifnextchar.{}{\ }}
\makeatother
\begin{document}
It is 8a.m. at the moment. \par
It is 8a.m.\xspace at the moment. \par
It is 8a.m.\ at the moment. \par
It is 8\amtime at the moment.
\end{document}


Note the use of \makeatletter and \makeatother. See What do \makeatletter and \makeatother do?.

However, it's easier to just use

It is 8a.m.\@ at the moment.


In the event that you might be using the macro as

It is 8\amtime, time to rise from bed.


the spacing will be incorrect. You could nest conditionals for checking the punctuation following \amtime:

\newcommand{\amtime}{a.m.\@ifnextchar.{}{\@ifnextchar,{}{\ }}}


However, this soon becomes clumsy. egreg's answer (using \@\xspace) provides a more elegant and encompassing alternative.

-