About
Shop
LaTeX
Software
Books
Gallery
News
Contact
Blog
Settings
Latest news 2019-11-04: The giveaway of two signed copies of “Quack, quack, quack. Give my hat back!” has closed and the winning entrants have been selected. Thank you to everyone who took part.


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.

\pgfcalendarweekdayname{week day number}

This expands to a textual representation of the day of the week, where the numbering starts from 0 (Monday).

\pgfcalendarweekdayshortname{week day number}

This expands to an abbreviated textual representation of the day of the week, (“Mon”, “Tue”, etc) where the numbering starts from 0 (Monday).

\pgfcalendarmonthname{month number}

This expands to a textual representation of the month name.

\pgfcalendarmonthshortname{month number}

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:

\number\day~\pgfcalendarmonthname{\month} \number\year

which produces:

19 March 2014

Alternatively, you can define a custom command called, say, \datefmt that formats any date:

\newcommand*{\datefmt}[3]{%
  \number#3~\pgfcalendarmonthname{#2} \number#1%
}

This has the syntax:

\datefmt{year}{month}{day}

so now today's date can be formatted using:

\datefmt{\year}{\month}{\day}

Alternatively, a specific date, for example, 2014-01-31 can be formatted using:

\datefmt{2014}{1}{31}

which produces:

31 January 2014

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:

\ifcasenumber
    ⟨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 \elsedefault 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

\ord{1}

produces:

1st

and

\ord{2}

produces:

2nd

etc. So the definition of \datefmt can now be defined as:

\newcommand*{\datefmt}[3]{%
  \ord{#3}~\pgfcalendarmonthname{#2} \number#1%
}

If you like, you can redefine \today to use this format:

\renewcommand*{\today}{\datefmt{\year}{\month}{\day}}

Take care if you use babel as it redefines \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:

\renewcommand*{\datebritish}{%
  \renewcommand*{\today}{\datefmt{\year}{\month}{\day}}%
}

Example 39. Custom Date Formatting

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:

\printdate{date}

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:

\newcount\julianday
\newcount\dayofweek

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:

\datefmt[day of week]{yyyy}{m}{d}

This command is defined as follows:

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:

\datefmt{2014}{1}{31}

and not worry about the week day.

Now this new \printdate command can be used in the document. For example:

\printdate{2014-05-last}

produces:

Saturday 31st May 2014

If you want \today to use the same format, then you can just redefine \today:

Again, you need to put this in the definition of \date⟨language if you are using babel.

You can download or view a complete document.

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:

\NeedsTeXFormat{format}[version]

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

\ProvidesPackage{name}[version]

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.

\RequirePackage[options]{name}[version]

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.

\endinput

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
}

Example 40. Custom Date Package

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}

You can download or view this 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).

© 2015 Dickimaw Books. "Dickimaw", "Dickimaw Books" and the Dickimaw parrot logo are trademarks. The Dickimaw parrot was painted by Magdalene Pritchett.

Terms of Use Privacy Policy Cookies Site Map FAQs