7.2 ⁂The pgfcalendar Package Utility Commands
The pgfcalendar package may be used independently of the pgf package, but if used without pgf (or tikz) the pgfkeys package also needs to be loaded:
\usepackage{pgfkeys} \usepackage{pgfcalendar}
or
\usepackage{pgfkeys,pgfcalendar}
In the command definitions below, ⟨date⟩ indicates a date specified using one of the following formats:
- A specific date:
⟨year⟩-⟨month⟩-⟨day⟩
- The last day of a particular month:
⟨year⟩-⟨month⟩-last
- An increment from a given date:
⟨year⟩-⟨month⟩-⟨day⟩+⟨increment⟩
or
⟨year⟩-⟨month⟩-last+⟨increment⟩
\year
for the current year); ⟨month⟩ is the month number
(for example, 6 for June or \month
for the current
month) and ⟨day⟩ is the day number (for example, 21
for the twenty-first of the month or \day
for the current day).
The ⟨increment⟩ (in days) may be either a positive or negative
number. If negative the leading + is still required. For
example, 2014-6-last+-4 means four days before the last day
of June.
The pgfcalendar provides the commands:
This converts a Gregorian date into the Julian day number and stores the result in ⟨register⟩, which must be a TeX register (not a LaTeX counter).
Example:
(Recall \newcount
from §2.1.3 Arithmetic.)
produces:
This converts a Julian day number to an ISO-date and stores the resulting year, month and day-of-month numbers in the control sequences ⟨year cs⟩, ⟨month cs⟩ and ⟨day cs⟩.
Example:
produces:
This converts a Julian day number to a week day number, where 0 indicates Monday, 1 indicates Tuesday, etc. The result is stored in the TeX register specified by ⟨register⟩.
Example:
produces:
(which indicates Thursday).
This tests the given date and does ⟨true code⟩ if the test succeeds otherwise it does ⟨false code⟩. The ⟨test⟩ may be one of the following key words:
- all
- Always yields true.
- Monday
- True if the date is a Monday.
- Tuesday
- True if the date is a Tuesday.
- Wednesday
- True if the date is a Wednesday.
- Thursday
- True if the date is a Thursday.
- Friday
- True if the date is a Friday.
- Saturday
- True if the date is a Saturday.
- Sunday
- True if the date is a Sunday.
- workday
- True if the date occurs from Monday to Friday, inclusive.
- weekend
- True if the date is a Saturday or Sunday.
- equals=⟨reference⟩
True if ⟨date⟩ is the same date as reference (where the year is specified in ⟨reference⟩) or has the same month and day parts as the reference (where the year is omitted from ⟨reference⟩).
- at least=⟨reference⟩
True if ⟨date⟩ is equal to ⟨reference⟩ or is a later date than ⟨reference⟩. If the year is omitted from ⟨reference⟩, only the month and day in ⟨date⟩ form part of the test.
- at most=⟨reference⟩
The reverse of the above.
- between=⟨start reference⟩ and ⟨end reference⟩
True if ⟨date⟩ lies between the two reference dates. If the year is omitted from the reference, only the month and day in ⟨date⟩ form part of the test.
- day of month=⟨number⟩
True if the day of the month in ⟨date⟩ is equal to ⟨number⟩.
- end of month=⟨number⟩
This is the reverse of the above in the sense that it's testing ⟨number⟩ against the day of the month counting backward from the end of the month. So end of month=1 yields true if ⟨date⟩ is the last day of the month, and end of month=2 yields true if ⟨date⟩ is the penultimate day of the month. If ⟨number⟩ is omitted, it's assumed to be 1.
Example:
2014-03-20 is in the \pgfcalendarifdate{2014-03-20}{at most=06-last} {first}% test true {second}% test false \space half of the year.
produces:
What happens if your date isn't in the form
⟨yyyy⟩-⟨m⟩-⟨d⟩? For example, it might
be in the form ⟨m⟩/⟨d⟩/⟨yyyy⟩.
Recall from §2.1.1 Macro Definitions that the \def
primitive can be used to define a macro that has a custom syntax.
It's therefore possible to define a command that will parse this syntax and
convert it:
(The \endparsemdydate
token is just an end placeholder, not
a command that needs defining.)
Now
\parsemdydate 3/19/2014\endparsemdydate
expands to 2014-3-19. Remember that if the date is stored in a macro, for example:
\newcommand*{\mydate}{3/19/2014}
then you first need to expand the macro before it can be parsed by
\parsemdydate
. (Recall \expandafter
from
§2.7.2 Iterating Over a Comma-Separated List.)
\expandafter\parsemdydate\mydate\endparsemdydate
Remember that the sample people.csv file and people SQL table included a date of birth field (labelled dob). This example computes the ages of each person in that data. This is done by first computing the Julian day number for today. Then for each person in the database, the Julian day number is computed for that person's date of birth. This number is subtracted from the Julian day number for today. This gives the total number of days since that person was born. This number is then divided by 356 to give an approximate age in years. (Recall TeX's integer arithmetic described in §2.1.3 Arithmetic.)
\documentclass[captions=tableheading]{scrartcl} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{pgfkeys,pgfcalendar} \usepackage{datatool} \DTLloaddb{people}{people.csv} \newcount\julianday \newcount\juliantoday \newcount\age % Compute the Julian day number for today: \pgfcalendardatetojulian{\year-\month-\day}{\juliantoday} \begin{document} Ages as of \number\year-\number\month-\number\day\␣are listed in Table~\ref{tab:ages}. \begin{table}[htbp] \caption{Ages} \label{tab:ages} \centering \begin{tabular}{lc} \bfseries Name & \bfseries Age% \DTLforeach*{people}% {\Forenames=forenames,\Surname=surname,\DoB=dob}% {% \\\Forenames\␣\Surname & % Compute the Julian day number for the date of birth \pgfcalendardatetojulian{\DoB}{\julianday}% % Compute \age = (\juliantoday - \julianday)/365 \age=\juliantoday \advance\age by -\julianday \divide\age by 365 \number\age }% \end{tabular} \end{table} \end{document}
This produces Table 7.1 and the text:
You can download or view this example. Remember that if your dates are in a different numerical format, for example, ⟨m⟩/⟨d⟩/⟨yyyy⟩, you need to convert them as described above. For example, replace
\pgfcalendardatetojulian{\DoB}{\julianday}
with
\pgfcalendardatetojulian {\expandafter\parsemdydate\DoB\endparsemdydate}{\julianday}
where \parsemdydate
is as described above.
This book is also available as A4 PDF or 12.8cm x 9.6cm PDF or paperback (ISBN 978-1-909440-07-4).