7.3 ⁂Displaying a Date
In addition to the utility commands described above, the pgfcalendar package also provides commands to display month names and the day of week names.
This expands to a textual representation of the day of the week, where the numbering starts from 0 (Monday).
This expands to an abbreviated textual representation of the day of the week, (“Mon”, “Tue”, etc) where the numbering starts from 0 (Monday).
This expands to a textual representation of the month name.
This expands to an abbreviated textual representation of the month name (“Jan”, “Feb”, etc).
If you want the name in another language, you need to load the translator package1 as well as babel [7]. For example:
\documentclass[french,german]{article} \usepackage{babel} \usepackage{translator} \usepackage{pgfkeys,pgfcalendar}
(Only a limited number of languages are supported.)
Example:
Today's date can be formatted using the month name:
which produces:
Alternatively, you can define a custom command called, say,
\datefmt
that formats any date:
This has the syntax:
so now today's date can be formatted using:
Alternatively, a specific date, for example, 2014-01-31 can be formatted using:
which produces:
If you want to use an ordinal instead of a plain number for the
day of the month (for example, 1st instead of 1), then you can use TeX's
\ifcase
conditional:
⟨case 0 code⟩%
\or
⟨case 1 code⟩%
\or
⟨case 2 code⟩%
\or
…
\else
⟨default code⟩%
\fi
This tests ⟨number⟩. If ⟨number⟩ equals 0, ⟨case 0 code⟩ is
performed. If ⟨number⟩ equals 1, ⟨case 1 code⟩ is performed.
If ⟨number⟩ equals 2, ⟨case 2 code⟩ is performed, etc. If none of
the cases match, ⟨default code⟩ is performed. (The \else
⟨default code⟩ part may be omitted.) Since there are a maximum of 31 days in
a month, 32 cases (including the unnecessary case 0) are needed:
\newcommand*{\ord}[1]{% \number#1% \ifcase#1\or st\or nd\or rd\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or st\or nd\or rd\or th\or th\or th\or th\or th\or th\or th\or st\fi }
Now
produces:
and
produces:
etc. So the definition of \datefmt
can now be defined as:
If you like, you can redefine \today
to use this format:
\today
every time the language changes (including at the beginning of the
document
environment). It does this via the commands
\date⟨language⟩
that are invoked when the current language
switches to ⟨language⟩. Each \date⟨language⟩
command
redefines \today
to use the format for ⟨language⟩. So if you
want to redefine \today
when you are using babel, you need
to redefine \date⟨language⟩
.
Example:
Suppose I'm using babel with the british
option. In
this case, the date is reset using \datebritish
so I need
to redefine it to use my own format instead:
Suppose now you want to include the day of the week in your custom date
format, or perhaps you want to be able to specify the date in the
ISO numeric format, with possibly an increment, as with the first argument
of \pgfcalendardatetojulian
.
Recall from §7.2 The pgfcalendar Package Utility Commands that the week day can be
obtained from a Julian day number using \pgfcalendarjuliantoweekday
and the Julian day number can be obtained from a date using
\pgfcalendardatetojulian
. In this example, I'm going to define
a new command called \printdate
with the syntax:
This will display the date in the form: ⟨day name⟩ ⟨day of month number⟩ ⟨month name⟩ ⟨year⟩. First, two new count registers need to be defined:
Next define the new command:
\newcommand*{\printdate}[1]{% \pgfcalendardatetojulian{#1}{\julianday}% \pgfcalendarjuliantodate{\julianday}{\thisyear}{\thismonth}{\thisday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% % Now display the date: \datefmt[\dayofweek]{\thisyear}{\thismonth}{\thisday}% }
The actual date format, including the day of week, is dealt with by
a new version of \datefmt
that now has four arguments:
This command is defined as follows:
\newcommand*{\datefmt}[4][]{% \ifstrempty{#1} {}% day of week missing {% \pgfcalendarweekdayname{#1}\space }% \ord{#4}~\pgfcalendarmonthname{#3} \number#2% }
This uses etoolbox's \ifstrempty
command to
omit the day of week name if the optional argument is absent. This
means that you can still directly use, for example:
and not worry about the week day.
Now this new \printdate
command can be used in the document.
For example:
produces:
If you want \today
to use the same format, then you can just redefine
\today
:
\renewcommand*{\today}{% \pgfcalendardatetojulian{\year-\month-\day}{\julianday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% \datefmt[\dayofweek]{\year}{\month}{\day}% }
Again, you need to put this in the definition of \date⟨language⟩
if you are using babel.
If this is a format you are likely to use in multiple documents, you might want to define your own custom package called, say, mycustomdate. This requires creating a file called mycustomdate.sty, that contains the following:
\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{mycustomdate}[2014/03/19 1.0 My custom date format] \RequirePackage{etoolbox} \RequirePackage{pgfkeys,pgfcalendar} % Command definitions for \printdate, \today, \datefmt % \ord (if required) and \date⟨language⟩ (if required). \endinput
This file should then be saved in your TEXMF path. For example, if you are using a Unix-like operating system, you can save it in, say, ~/texmf/tex/latex/mystuff/ (see Volume 1).
If you're unfamiliar with writing packages, here's a brief explanation of the commands used above:
This should be the first statement of any class or package and is used to identify the TeX format and, optionally, the version date. For a LaTeX2e class or package, the ⟨format⟩ should be LaTeX2e. (Other formats may not define this command.) The version date, if present, must be in the numeric form ⟨yyyy⟩/⟨mm⟩/⟨dd⟩ (two digits are required for both the month and day numbers).
This command identifies the package name and optionally a version. The ⟨name⟩ should match the filename (without the extension), so a package called mycustomdate should be in a file called mycustomdate.sty. The ⟨version⟩ should start with a numeric date in the form ⟨yyyy⟩/⟨mm⟩/⟨dd⟩ and may optionally be followed by a version number and a brief description.
This is analogous to \usepackage
but is for use in a class or
package. The final optional argument ⟨version⟩ indicates that
the package must be at least that version. If an older version is
installed a warning is issued.
This is a TeX primitive that instructs TeX to stop reading the current
file. Anything following this command is skipped. (Some packages have their
documentation in the .sty file after \endinput
, but this
practice has been deprecated in favour of providing the documentation as a PDF.)
Once you have added mycustomdate.sty to your TeX path, you can now load this package in your document via
\usepackage{mycustomdate}
Take care if you need to use babel. If this custom package includes code
to redefine \date⟨language⟩
you will need to load
babel first (and remember to load the
translator package as well for the month and day of week
names). Alternatively, you can
check for the existence of \date⟨language⟩
at the start of
the document
environment, and redefine it if it exists:
\AtBeginDocument{% \ifdef{\datebritish}% check if \datebritish exists {% it does exist, so redefine it \renewcommand*{\datebritish}{% \renewcommand*{\today}{% \pgfcalendardatetojulian{\year-\month-\day}{\julianday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% \datefmt[\dayofweek]{\year}{\month}{\day}% }% }% \datebritish }% {}% doesn't exist, do nothing }
Putting the above together, here's a complete example that defines a package that uses a British date format:
\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{mycustomdate}[2014/03/19 1.0 My custom date format] \RequirePackage{etoolbox}% \RequirePackage{pgfkeys,pgfcalendar} % Define an ordinal command: \newcommand*{\ord}[1]{% \number#1% \ifcase#1\or st\or nd\or rd\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or th\or st\or nd\or rd\or th\or th\or th\or th\or th\or th\or th\or st\fi } % Define registers needed by \printdate: \newcount\julianday \newcount\dayofweek % Define generic date format: \newcommand*{\datefmt}[4][]{% \ifstrempty{#1} {}% day of week missing {% \pgfcalendarweekdayname{#1}\space }% \ord{#4}~\pgfcalendarmonthname{#3} \number#2% } % Define command to read ISO date and then use \datefmt \newcommand*{\printdate}[1]{% \pgfcalendardatetojulian{#1}{\julianday}% \pgfcalendarjuliantodate{\julianday}{\thisyear}{\thismonth}{\thisday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% % Now display the date: \datefmt[\dayofweek]{\thisyear}{\thismonth}{\thisday}% } % Redefine \today to use the same format: \renewcommand*{\today}{% \pgfcalendardatetojulian{\year-\month-\day}{\julianday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% \datefmt[\dayofweek]{\year}{\month}{\day}% } % Check if babel is used with the british option: \AtBeginDocument{% \ifdef{\datebritish}% check if \datebritish exists {% it does exist, so redefine it \renewcommand*{\datebritish}{% \renewcommand*{\today}{% \pgfcalendardatetojulian{\year-\month-\day}{\julianday}% \pgfcalendarjuliantoweekday{\julianday}{\dayofweek}% \datefmt[\dayofweek]{\year}{\month}{\day}% }% }% \datebritish }% {}% doesn't exist, do nothing } \endinput
(You can download this package.)
And here's a document that uses this package:
\documentclass{article} \usepackage{mycustomdate} \begin{document} Today: \today. Tomorrow: \printdate{\year-\month-\day+1}. Yesterday: \printdate{\year-\month-\day+-1}. The first day of this month: \printdate{\year-\month-1}. The last day of this month: \printdate{\year-\month-last}. A specific date: \printdate{2014-3-20}. A date without the day of week: \datefmt{2014}{3}{20}. \end{document}
Footnotes
- ... package1
- provided with beamer [103]
This book is also available as A4 PDF or 12.8cm x 9.6cm PDF or paperback (ISBN 978-1-909440-07-4).