% \iffalse meta-comment
%
% Copyright (C) 2025 Alan J. Cain
%
% This file may be distributed and/or modified under the conditions of the LaTeX Project Public Licence, either version
% 1.3c of this licence or (at your option) any later version. The latest version of this licence is in:
%
% http://www.latex-project.org/lppl.txt
%
% and version 1.3c or later is part of all distributions of LaTeX version 2008-05-04 or later.
%
% \fi
%
% \iffalse
%<*driver>
\PassOptionsToPackage{inline}{enumitem}
\documentclass{l3doc}



% Make space for larger numbers in contents

\makeatletter
\ExplSyntaxOn

\cs_gset:Npn \l@subsection { \@dottedtocline{2}{2.5em}{2.8em} }
\cs_gset:Npn \l@subsubsection { \@dottedtocline{3}{5.3em}{4em} }

\ExplSyntaxOff
\makeatother



% Link formatting

\usepackage{xcolor}

\definecolor{linkcolor}{rgb}{0.0,0.4,0.7}
\colorlet{citecolor}{linkcolor}
\colorlet{urlcolor}{linkcolor}

\hypersetup{
  linkcolor=linkcolor,%
  citecolor=citecolor,%
  urlcolor=urlcolor,%
}

\newcommand*\fullref[2]{%
  \hyperref[#2]{#1\penalty 200\ \ref*{#2}}%
}



% Use siunitx for typesetting dimensions

\usepackage{siunitx}
\sisetup{
  mode=match,
}
\DeclareSIUnit\point{pt}



% Listings and grammars

\usepackage{listings}
\lstset{
  language=[LaTeX]TeX,
  basicstyle=\small\ttfamily,
  basewidth=0.5em,
  numbers=left,
  numberstyle=\scriptsize\sffamily,
}

\usepackage{simplebnf}



% Macros for describing keys

\newlist{optionlist}{description}{1}
\setlist[optionlist]{
  leftmargin=3em,
  style=unboxed,
  labelsep=1em,
  font=\descriptionitemcolon,
  nosep,
}
\newcommand*{\descriptionitemcolon}[1]{\kern 1em #1:}


\newcommand*\key[1]{\texttt{#1}}
\newcommand*\val[1]{\texttt{#1}}
\newcommand*\keyval[2]{\texttt{#1=#2}}

\usepackage{xcolor}
\definecolor{keycolor}{rgb}{0.8,0.0,0.0}
\definecolor{keyvaluecolor}{rgb}{0.0,0.65,0.0}

\ExplSyntaxOn

\NewDocumentEnvironment{describekey}{ m m m }{
  \group_begin:
  \group_begin:
  \noindent{\textcolor{keycolor}{\texttt{#1}}}
  \str_if_empty:nF{#2}
    {
      \skip_set:Nn{\parfillskip}{0pt}
      \str_case:nnF{#2}
      {
        {style}
        {
          \hfil
          (style,~initially~#3)
        }
        {keys}
        {
          \hfil
          (key–value~pairs,~initially~#3)
        }
      }
      {
        \textcolor{keyvaluecolor}{\texttt{=}\meta{#2}}
        \str_if_empty:nF{#3}
          {
            \hfil
            (default\nobreakspace\texttt{#3})
          }
      }
    }
  \par
  \group_end:
  \nobreak
  \skip_add:Nn{\leftskip}{\parindent}
  \noindent\ignorespaces
}{
  \par
  \group_end:
}

\ExplSyntaxOff


\newcommand*\mcode[1]{\texttt{#1}}
\newcommand*\param[1]{\texttt{\##1}}



% Other macros

\newcommand*\TikZ{\texorpdfstring{Ti\textit{k}Z}{TikZ}}
\newcommand*\ISO{\textsc{iso}}



% Timechart

\usepackage{timechart}

\input{timechart-example1-setup.tex}



\begin{document}
\DocInput{timechart.dtx}
\end{document}
%</driver>
% \fi
%
%
%
% \GetFileInfo{timechart.sty}
%
%
%
% \title{^^A
% \pkg{timechart} ^^A
%   --- A package for drawing chronological charts^^A
%   \thanks{This file describes \fileversion, last revised \filedate.}^^A
% }
%
% \author{^^A
%  Alan J. Cain\thanks{Email:~\texttt{a.j.cain (AT) gmail.com}}^^A
% }
%
% \date{Released \filedate}
%
% \maketitle
%
%
%
% \begin{abstract}
%   This package provides for the easy creation of chronological charts which show visually the relative historical
%   positions of people and events. Each event or period can be specified by a single line of \LaTeX\ code comprising
%   (possibly uncertain) start and finish dates and a label, and the package takes care of indicating the uncertainties
%   and whether intervals extend beyond the specified bounds of the chart.
% \end{abstract}
%
%
%
% \tableofcontents
%
%
%
% \begin{documentation}
%
% \setcounter{secnumdepth}{2}
%
%
% \section{Introduction}
%
% The \pkg{timechart} package provides a system for the easy creation of chronological charts --- of the type pioneered
% by Joseph Priestley (1733--1804) in his `Chart of Biography' and more famously in his `New Chart of
% History'\footnote{\textsc{url}:~\url{https://commons.wikimedia.org/wiki/File:A_New_Chart_of_History_color.jpg}} ---
% which can show visually the relative historical positions of people and events. An example of what \pkg{timechart} can
% be used to produce is shown in \fullref{Figure}{fig:example1} on page~\pageref{fig:example1}.
%
% \begin{figure}[p]
%   \centering
%   \input{timechart-example1-timechart.tex}
%   \caption{Timechart showing the lifetimes of Roman emperors from \timechartmakebeforeyear{50} to
%   \timechartmakeafteryear{500}. Marks on each lifetime indicate the beginning (and, where relevant, the end) of that
%   emperor's reign. Colours generally indicate dynasties, with shades of green indicating periods when the imperial
%   power shifted between many short-reigning emperors.}
%   \label{fig:example1}
% \end{figure}
%
% Essentially (and this was a design requirement), \emph{only one line} of \LaTeX\ code is required for each interval
% (which, in the case of \fullref{Figure}{fig:example1}, are mostly lifetimes). The \pkg{timechart} package takes care
% of indicating ranges of possible dates by suitable fading from or to transparency. It also handles indicators to show
% that intervals continue outside the specified scope of the chart.
%
% \pkg{timechart} was developed from, and replaced, a set of macros used to create the chronological charts in the
% author's book \textit{Form \& Number: A History of Mathematical Beauty}, which is available on the Internet Archive
% under a Creative Commons licence.\footnote{\textsc{url}:
% \url{https://archive.org/details/cain_formandnumber_ebook_large}}
%
%
%
% \paragraph*{Licence.} \noindent\pkg{timechart} is released under the \LaTeX\ Project Public Licence v1.3c or
% later.\footnote{\textsc{url}: \url{https://www.latex-project.org/lppl.txt}}
%
%
%
% \paragraph*{Acknowledgements.} The author thanks Tânia Paulista for reading and commenting on an earlier draft of the
% documentation.
%
%
%
% \section{Requirements}
%
% \pkg{timechart} requires PGF/\TikZ\ and a \LaTeX\ kernel with \pkg{expl3} support (any kernel version since 2020-02-02
% should suffice).
%
%
%
% \section{Installation}
%
% To install manually, run \texttt{tex timechart.ins} and copy the file \file{timechart.sty} to somewhere \LaTeX\ can
% find it.
%
%
%
% \section{Getting started}
%
% The \pkg{timechart} package is loaded as usual via \cs{usepackage}\texttt{\{timechart\}}. There are no package
% options.
%
% The small example in \fullref{Section}{sec:example} illustrates the basic principles of \pkg{timechart}.
% \fullref{Section}{sec:full-example} shows the full code used to produce the large example in \fullref{Figure}{fig:example1}.
%
%
%
%
%
% \section{Example}
% \label{sec:example}
%
% This section illustrates how to create the small chart shown in \fullref{Figure}{fig:example2-v2} on
% page~\pageref{fig:example2-v2}.
%
% The basic environment is \env{timechart}, which includes the specification of the start and finish years. The start
% year \timechartmakebeforeyear{50} is specified as \mcode{-50}, the finish year \timechartmakeafteryear{75} as
% \mcode{75}. Each interval in the chart is specified using the \cs{timechartinterval} command, which takes three
% mandatory parameters: a start year, a finish year, and a label. The following code produces the flawed preliminary
% version shown in \fullref{Figure}{fig:example2-v1}.
%
% \lstinputlisting{timechart-example2-v1.tex}
%
% \begin{figure}[ht]
%   \centering
%   \input{timechart-example2-v1.tex}
%   \medskip
%   \caption{Flawed preliminary version of a chart showing the lifetimes of Roman emperors of the Julio-Claudian
%   dynasty. (The final version is shown in \fullref{Figure}{fig:example2-v2}.)}
%   \label{fig:example2-v1}
% \end{figure}
%
% This first attempt result illustrates some of the principles of \pkg{timechart}. Each interval has been placed on its
% own line. More precisely, the \(y\) coordinate of the first interval is \(0\) and each use of \cs{timechartinterval}
% increments the `current \(y\) coordinate' by a specified amount. (Various commands are available to set the \(y\)
% coordinate manually or to reset it automatically when it passes certain bounds; see
% \fullref{Subsection}{subsec:positioning}.) Horizontally, the chart starts and finishes at the specified years. The topmost
% interval, indicating Augustus' life, has been truncated with an indicator that it begins before the specified start
% year of the chart. Vertically, the chart has been sized to fit around the specified intervals.
%
% But this version is hardly satisfactory, for many reasons. The chart finishes between two minor ticks on the axis,
% because the intervals between major and minor ticks default respectively to 10 years and 50 years. The black intervals
% and text do not contrast well with the black axis and grid. The serif font is perhaps not best suited to label the
% intervals. And the label `Augustus' has been lost, since labels are by default placed on the left of intervals. To
% rectify these problems, some changes are necessary, all of which can be made using key-value syntax in an optional
% parameter to the \env{timechart} environment or the \cs{timechartinterval} command:
% \begin{enumerate}
%     \item Set the intervals between major and minor ticks to 5 years and 25 years respectively, by setting
%           \keyval{minor tick interval}{5} and \keyval{major tick interval}{25}.
%     \item Change the colour of the grid to light grey by appending \keyval{draw}{lightgray} to the \key{grid} style
%     \item Change the colour of the axis to grey by appending \keyval{draw}{gray} to the \key{axis line}, \key{minor
%           tick}, and \key{major tick} styles.
%     \item Change the font used for interval labels to small san-serif by appending \keyval{node
%           font}{\cs{sffamily}\cs{small}} to the \key{interval label} style
%     \item Change the colour of the intervals by defining a style \key{julioclaudian} that sets \keyval{interval bar
%           color}{red!80!black} and applying it to each interval via its optional argument. (While \key{interval bar
%           color} could be set locally for each interval, it is better to define a style that corresponds to the
%           semantic meaning of the colour: in this case, a single dynasty.)
%     \item Use the \key{right} key to place some labels on the right
% \end{enumerate}
%
% The result is the following code, which produces \fullref{Figure}{fig:example2-v2}.
%
% \lstinputlisting{timechart-example2-v2.tex}
%
% \begin{figure}[ht]
%   \centering
%   \input{timechart-example2-v2.tex}
%   \caption{Chart showing the lifetimes of Roman emperors of the Julio-Claudian dynasty.}
%   \label{fig:example2-v2}
% \end{figure}
%
%
%
% \section{Configuration}
%
% All \pkg{timechart} configuration, global or local, is via PGF keys, so some familiarity with their use is beneficial;
% see the PGF/\TikZ\ manual.
%
% Configuration keys for \pkg{timechart} are contained in \key{/timechart/} in the PGF keys hierarchy. The
% \meta{options} passed to the \env{timechart} environment or any of the commands \cs{timechartinterval},
% \cs{timecharttext}, or \cs{timechartspace} are processed within \key{/timechart/} (since \key{/timechart/.cd} is
% executed before keys are processed).
%
% The user may wish to define PGF styles for different kinds of interval within a chart. For example, one could
% define styles \key{science} and \key{art} that set a particular colour for the interval, and write
% \cs{timechartinterval}\key{[science]}\marg{birth}\marg{death}\marg{name} or
% \cs{timechartinterval}\key{[art]}\marg{birth}\marg{death}\marg{name} to distinguish visually the lifetimes of
% various scientists and artists.
%
%
%
% \section{Specifying dates and date ranges}
% \label{sec:dates-and-ranges}
%
% Using \pkg{timechart} requires specification of dates and date ranges for the start and finish of each interval, both
% of which may be uncertain.
%
% The basic specification of a date uses \ISO~8601 format \mcode{YYYY-MM-DD}. This format specifies a date with
% day-level precision; use \mcode{YYYY-MM} and \mcode{YYYY} for month- and year-level precision. If the date is prefixed
% by \mcode{-}, it is treated as the corresponding date before the epoch. (This is a difference with \ISO~8601, in which
% \texttt{0} represents \timechartmakebeforeyear{1}, \texttt{-1} represents \timechartmakebeforeyear{2}, and so on.) So
% (assuming that one is using \textsc{bce}/\textsc{ce}) one uses \mcode{-100} to indicate \timechartmakebeforeyear{100}
% and \mcode{100} to indicate \timechartmakeafteryear{100}. (The era indicators `\textsc{bce}' and `\textsc{ce}' appear
% on the axis. Alternative era indicators --- or a different epoch --- can be specified; see
% \fullref{Section}{sec:era-indicators}.)
%
% A date can be prefixed with a \mcode{c} to indicate `circa', such as \mcode{c-100} for `circa
% \timechartmakebeforeyear{100}' and \mcode{c100} for `circa \timechartmakeafteryear{100}'. When an interval is drawn in
% a chart, `circa' will be indicated by automatically creating (or extending) a range according to the value of the key
% \key{circa uncertainty} (see \fullref{Subsection}{subsec:intervals}).
%
% A date range comprises two dates (each with or without \mcode{c}) separated by a slash \mcode{/}, with the first date
% being earlier (or equal to) the second date. (The slash indicates a range of dates per \ISO~8601.) A date
% range can be used to indicate a broader uncertainty than the default `circa', or to indicate a definite range within
% which an interval starts or ends.
%
% \begin{description}
%     \item[Examples of correctly formatted dates and date ranges:] \mcode{-50}, \mcode{100}, \mcode{c-50},
%           \mcode{c100}, \mcode{-50/100}, \mcode{c-50 / +100}, \mcode{-50/c100}, \mcode{c-50/c100}, \mcode{-585-05-28},
%           \mcode{1947-12-01}, \mcode{1989-11}.
%
%     \item[Examples of incorrectly formatted date and date ranges:] \mcode{100?}, \mcode{100CE}, \mcode{100BCE},
%           \mcode{-50-100}, \mcode{100/-50}.
% \end{description}
%
% \noindent That is, the syntax for dates and date ranges is per the following (not-quite-formal) grammar:
%
% \smallskip
%
% \begin{bnf}
%   \meta{cdate-or-crange} ::= \meta{cdate}
%   | \meta{crange} ;;
%   \meta{cdate} ::= \meta{date}
%   | \mcode{c}\meta{date} ;;
%   \meta{date} ::= \meta{pdate}
%   | \mcode{-}\meta{pdate} ;;
%   \meta{pdate} ::= \meta{year}\mcode{-}\meta{month}\mcode{-}\meta{day}
%   | \meta{year}\mcode{-}\meta{month}
%   | \meta{year} ;;
%   \meta{crange} ::= \meta{\(\text{date}_1\)}\mcode{/}\meta{\(\text{date}_2\)}
%   | \mcode{c}\meta{\(\text{date}_1\)}\mcode{/}\meta{\(\text{date}_2\)}
%   | \meta{\(\text{date}_1\)}\mcode{/}\mcode{c}\meta{\(\text{date}_2\)}
%   | \mcode{c}\meta{\(\text{date}_1\)}\mcode{/}\mcode{c}\meta{\(\text{date}_2\)} ~~~(with \(\text{date}_1 \leq \text{date}_2\)) ;;
% \end{bnf}
%
% \smallskip
%
% \noindent The bounds of the \env{timechart} environment (see \fullref{Section}{sec:timechart-env}) must satisfy
% \meta{cdate} in this grammar (although only the \meta{year} is used); the start and finish dates of an
% \cs{timechartinterval} command (see \fullref{Subsection}{subsec:intervals}) must satisfy \meta{cdate-or-crange}; the
% parameter of an \cs{timecharttext} command (see \fullref{Subsection}{subsec:text}) must satisfy \meta{date}.
%
% \medskip
% \noindent \textit{Note.} For performance reasons, the date parser does only limited error-checking. Months outside the
% range from \mcode{01} to \mcode{12} or days outside the range of the specified month will be ignored. Otherwise
% malformed dates or date ranges may produce obscure error messages or unexpected results.
%
%
%
% \section{\env{timechart} environment}
% \label{sec:timechart-env}
%
% \begin{function}{timechart}
%   \begin{syntax}
%     \cs{begin}\texttt{\{}\env{timechart}\texttt{\}}\oarg{options}\marg{start}\marg{finish}
%       \meta{content}
%     \cs{end}\texttt{\{}\env{timechart}\texttt{\}}
%   \end{syntax}
%   This is the main environment for creating a chronological chart. The mandatory arguments \meta{start} and
%   \meta{finish} specify the first and last years of the chart. These can be dates with circa indicators (that is, they
%   satisfy \meta{cdate} in the grammar in \fullref{Section}{sec:dates-and-ranges}), but the circa specifier has no
%   effect and only the `year' part of the date is used. The optional argument \meta{options} supplies PGF keys that
%   apply to the entire chart.
%
%   The \meta{content} comprises commands like \cs{timechartinterval}, \cs{timecharttext}, \cs{timechartspace},
%   commands for positioning, as described in \fullref{Section}{sec:within}, and the user's own \TikZ\ code.
% \end{function}
%
%
%
% \subsection{General configuration of the \env{timechart} environment}
%
% \begin{describekey}{/timechart/width}{dimension}{\cs{textwidth}}
%   The width of the chart. This refers to the width of the grid and axis of the chart, not
%   including intervals that pass beyond the specified limits of the chart, or axis labels that protrude beyond the
%   width of the axis itself.
% \end{describekey}
%
%
% \begin{describekey}{/timechart/tolerance}{dimension}{5pt}
%   The length by which an interval is allowed to pass beyond the limits of the chart before it `counts' as doing so
%   and the appropriate indicator is drawn.
% \end{describekey}
%
%
% \begin{describekey}{/timechart/beyond length}{dimension}{5pt}
%   The length of the indicator that an interval passes beyond the limits of the chart.
% \end{describekey}
%
% \begin{describekey}{/timechart/beyond x radius}{dimension}{4pt}
%   The horizontal radius of the concave part of the indicator that an interval passes beyond the limits of the chart.
%   (The vertical radius will be half the thickness of the bar.)
% \end{describekey}
%
% \begin{describekey}{/timechart/ystep}{dimension}{-10pt}
%   The default length (positive or negative) by which the current \(y\) coordinate is automatically adjusted after each
%   interval, text, or space is placed.
% \end{describekey}
%
% \begin{describekey}{/timechart/minor tick interval}{number}{10}
%   The number of years (which must be positive) between each minor tick on the axis.
% \end{describekey}
%
% \begin{describekey}{/timechart/major tick interval}{number}{50}
%   The number of years (which must be positive) between each major tick on the axis and each vertical line in the grid.
% \end{describekey}
%
%
%
% \subsection{Tagging support}
%
% The following four keys are used for tagging the chart. They simply forward to the corresponding \TikZ\ keys, which
% are only defined if \cs{DocumentMetadata} is used. Using these keys when \cs{DocumentMetadata} is not used will cause
% an error. See the tagging documentation for further details of what these keys do.
%
% \begin{describekey}{/timechart/alt}{text}{[None]}
%   Sets \code{alt} text for the chart.
% \end{describekey}
%
% \begin{describekey}{/timechart/actualtext}{text}{[None]}
%   Sets \code{actualtext} text for the chart.
% \end{describekey}
%
% \begin{describekey}{/timechart/artifact}{}{}
%   Tag the chart as an artifact.
% \end{describekey}
%
% \begin{describekey}{/timechart/tagging-setup}{keys}{empty}
%   Configure tagging for the chart.
% \end{describekey}
%
%
%
% \subsection{Grid configuration}
%
% \begin{describekey}{/timechart/no grid}{}{}
% Do not draw the grid.
% \end{describekey}
%
% \begin{describekey}{/timechart/grid top ysep}{dimension}{3pt}
% Distance between the top of the grid and the topmost interval or space.
% \end{describekey}
%
% \begin{describekey}{/timechart/grid bottom ysep}{dimension}{3pt}
% Distance between the bottom of the grid and the bottommost interval or space.
% \end{describekey}
%
% \begin{describekey}{/timechart/grid}{style}{empty}
% Style for drawing the grid.
% \end{describekey}
%
%
%
% \subsection{Axis configuration}
%
% \begin{describekey}{/timechart/axis}{position}{above}
%   Where and whether to draw the axis. \meta{position} may be \val{above}, \val{below}, or
%   \val{none}.
% \end{describekey}
%
% \begin{describekey}{/timechart/no axis}{}{}
%   Do not draw the axis. Equivalent to \keyval{/timechart/axis}{none}.
% \end{describekey}
%
% \begin{describekey}{/timechart/axis line}{style}{\keyval{line cap}{rect}}
%   Style for drawing the axis line.
% \end{describekey}
%
% \begin{describekey}{/timechart/minor tick}{style}{empty}
%   Style for drawing minor ticks.
% \end{describekey}
%
% \begin{describekey}{/timechart/minor tick length}{dimension}{1.5mm}
%   Length of minor ticks.
% \end{describekey}
%
% \begin{describekey}{/timechart/major tick}{style}{empty}
%   Style for drawing major ticks.
% \end{describekey}
%
% \begin{describekey}{/timechart/major tick length}{dimension}{3mm}
%   Length of major ticks.
% \end{describekey}
%
% \begin{describekey}{/timechart/major tick label}{style}{as described below}
%   Style for labels on the major ticks on the axis. The intial style essentially sets \keyval{inner sep}{0},
%   \keyval{outer sep}{0}, \keyval{anchor}{mid west}, \keyval{rotate}{90}.
% \end{describekey}
%
% \begin{describekey}{/timechart/major tick eras}{locations}{outer}
%   Which major tick labels have era indicators. \meta{locations} may be \val{none}, \val{all}, or \val{outer} (which
%   means that only the first and last labels have era indicators). This option does not affect the epoch marker (see
%   \fullref{Subsection}{subsec:year-zero}).
% \end{describekey}
%
%
%
% \section{Within the \env{timechart} environment}
% \label{sec:within}
%
%
%
% \subsection{Intervals}
% \label{subsec:intervals}
%
% \begin{function}{\timechartinterval}
%   \begin{syntax}
%     \cs{timechartinterval}\oarg{options}\marg{start}\marg{finish}\marg{label}
%   \end{syntax}
%   This command creates an interval in the chart at the current \(y\) coordinate between the specified \meta{start} and
%   \meta{finish}, with the given \meta{label}. These arguments are mandatory. Each of \meta{start} and \meta{finish}
%   can be either a year or a range of years, possibly with circa markers. That is, each must satisfy
%   \meta{cyear-or-crange} in the grammar in \fullref{Section}{sec:dates-and-ranges}.
%
%   The optional argument \meta{options} specifies PGF keys within \key{/timechart/} that are applied locally to the
%   interval.
%
%   The current \(y\) coordinate will be adjusted according to \key{/timechart/ystep} unless \key{/timechart/no
%   autostep} has been set.
% \end{function}
%
%
%
% \subsubsection{Interval configuration}
%
% \begin{describekey}{/timechart/no autostep}{}{}
%   Do not automatically alter the current \(y\) coordinate by the amount specified in \key{/timechart/ystep}.
% \end{describekey}
%
% \begin{describekey}{/timechart/ref}{label}{none}
%   Make the interval label a hyperlink to the position labelled by \meta{label}.
% \end{describekey}
%
% \begin{describekey}{/timechart/mark}{comma-separated list of years}{empty}
%   Draw marks in the interval at the years contained in the list. Each entry in the list must be a definite year (that
%   is, must satisfy \meta{year} in the grammar in \fullref{Section}{sec:dates-and-ranges}), must lie in the definite
%   part of the interval (not in the start or finish ranges) and cannot lie beyond the bounds of the chart on a side
%   where there interval exceeds tolerance. The colour of marks can be specified using \key{/timechart/interval mark
%   color}. \key{/timechart/marks} is a synonym for this key.
% \end{describekey}
%
% \begin{describekey}{/timechart/circa uncertainty}{number}{3}
%   Treat a circa indicator \mcode{c} as indicating an uncertainity of \(\pm\meta{number}\).
% \end{describekey}
%
% \begin{describekey}{/timechart/interval minimum width}{dimension}{1pt}
%   Ensure that any interval has a width of at least \meta{dimension}. This is useful to ensure that a single event is
%   visible in the chart.
%
%   If an interval is specified with start and finish ranges, and with \keyval{start range}{fade} and \keyval{finish
%   range}{fade}, then the `certain' portion of the interval will also have width at least \meta{dimension}. (This
%   restriction prevents a common rendering error where start and finish fadings around a `certain' interval of length
%   \(0\) would not quite meet.)
% \end{describekey}
%
% \begin{describekey}{/timechart/interval bar color}{color}{black}
%   Fill the interval bar with \meta{color}.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval bar thickness}{dimension}{8pt}
%   Set the vertical thickness of the interval bar to \meta{dimension}.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval bar node name}{string}{bar node}
%   Set the name of the node containing the interval bar to \meta{string}.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval mark color}{color}{gray}
%   Draw marks using \meta{color}.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label}{style}{empty}
%   Style to apply to an interval label.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label centered}{style}{as below}
%   Style to apply to an interval label placed centrally. Initially, this style executes the style
%   \key{/timechart/interval label} and sets \keyval{text}{white}. The reason for a separate style for centred labels is
%   that often a contrasting colour will be required. For instance, labels positioned to the left and right may be
%   black, but if the bar is black, a centred label should be a light colour.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label centered background}{style}{as below}
%   Style to apply to the `background' interval label placed centrally. Initially, this style executes
%   \key{/timechart/interval label}. The `background' interval label is simply the usual label and is placed in the same
%   location, but on a layer behind the bar and, unlike the label itself, is not clipped. The reason for this style is
%   that if the bar is narrow, part of the label text (such as ascenders and/or descenders) may naturally extend beyond
%   the bar itself and it may be useful that thse should appear in a different colour.
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label baseline}{dimension}{-3pt}
%   Position the baseline of the interval label \meta{dimension} below the current \(y\) coordinate (which is the
%   midpoint of the interval bar).
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label pos}{position}{left}
%   Specify where to place the label relative to the interval bar: \meta{position} may be \val{left}, \val{center}, or
%   \val{right}. The position \val{center} places the label at the midpoint of \emph{the visible segment of the solid
%   part} of the interval bar (that is, not including fading at the start or finish of the bar, and not including part
%   of the bart that would extend beyond the bounds of the chart). Further, a centred label is clipped to the size of
%   the bar and a unclipped `background' copy of it is drawn behind the bar, so that the portion appearing `on' and
%   `outside' the bar can have different styles. (See the keys \key{/timechart/interval label centered} and
%   \key{/timechart/interval label centered background}.)
% \end{describekey}
%
% \begin{describekey}{/timechart/interval label node name}{string}{label node}
%   Set the name of the node containing the interval label to \meta{string}.
% \end{describekey}
%
% \begin{describekey}{/timechart/start range}{range-type}{fade}
%   Type of indication of the range where an interval may start. \meta{range-type} can be \val{fade}, which produces an
%   indicator like \timechartlegendstartrange[legend item width=8mm], or \val{slant}, which produces
%   \timechartlegendstartrange[legend item width=8mm,start range=slant].
% \end{describekey}
%
% \begin{describekey}{/timechart/finish range}{range-type}{fade}
%   Type of indication of the range where an interval may finish. \meta{range-type} can be \val{fade}, which produces an
%   indicator like \timechartlegendfinishrange[legend item width=8mm], or \val{slant}, which produces
%   \timechartlegendfinishrange[legend item width=8mm,finish range=slant].
% \end{describekey}
%
%
%
% \subsection{Text}
% \label{subsec:text}
%
% \begin{function}{\timecharttext}
%   \begin{syntax}
%     \cs{timecharttext}\oarg{options}\marg{year}\marg{text}
%   \end{syntax}
%   Place \meta{text} in the time chart at the current \(y\) coordinate and at the horizontal position of \meta{year},
%   which must be a definite year (that is, must satsify \meta{year} in the grammar in
%   \fullref{Section}{sec:dates-and-ranges}).
%
%   The optional argument \meta{options} specifies PGF keys within \key{/timechart/} that are applied locally.
%
%   The current \(y\) coordinate will be adjusted according to \key{/timechart/ystep} unless \key{/timechart/no
%   autostep} has been set.
% \end{function}
%
%
%
% \subsubsection{Text configuration}
%
% \begin{describekey}{/timechart/text node name}{string}{text node}
%   Set the name of the node containing the text to \meta{string}.
% \end{describekey}
%
% \begin{describekey}{/timechart/text}{style}{empty}
%   Style to apply to the text.
% \end{describekey}
%
% \begin{describekey}{/timechart/text baseline}{dimension}{-3pt}
%   Position the baseline of the text \meta{dimension} below the current \(y\) coordinate.
% \end{describekey}
%
% \begin{describekey}{/timechart/text pos}{position}{left}
%   Specify where to place the label relative to the given \meta{year}: \meta{position} may be \val{left}, \val{center},
%   or \val{right}.
% \end{describekey}
%
%
%
% \subsection{Space}
%
% \begin{function}{\timechartspace}
%   \begin{syntax}
%     \cs{timechartspace}\oarg{options}
%   \end{syntax}
%   Create a space in the time chart at the current \(y\) coordinate, with the same effect on vertical spacing as an
%   interval. More precisely, the current \(y\) coordinate will be adjusted according to \key{/timechart/ystep} unless
%   \key{/timechart/no autostep} has been set.
%
%   The optional argument \meta{options} specifies PGF keys within \key{/timechart/} that are applied locally.
% \end{function}
%
%
%
% \subsection{Positioning}
% \label{subsec:positioning}
%
% The commands \cs{timechartinterval}, \cs{timecharttext}, and \cs{timechartspace} all act at the current \(y\)
% coordinate and change its value according to \key{/timechart/ystep} (unless \key{/timechart/no autostep} is used).
% There are several functions to set the current \(y\) coordinate and to have it reset automatically.
%
% \begin{function}{\timechartsety}
%   \begin{syntax}
%     \cs{timechartsety}\marg{dimension}
%   \end{syntax}
%   Set the current \(y\) coordinate to \meta{dimension}.
% \end{function}
%
% \begin{function}{\timechartsavey}
%   \begin{syntax}
%     \cs{timechartsavey}
%   \end{syntax}
%   Save the current \(y\) coordinate. If \cs{timechartresety} is used, the \(y\) coordinate resets to the last saved
%   \(y\) coordinate. If the current \(y\) coordinate exceeds the minimum or maximum set by
%   \cs{timechartsetyminimumautoreset} and \cs{timechartsetymaximumautoreset}, it will be reset to the last saved \(y\)
%   coordinate.
% \end{function}
%
% \begin{function}{\timechartresety}
%   \begin{syntax}
%     \cs{timechartresety}
%   \end{syntax}
%   Reset the \(y\) coordinate to the last coordinate saved using \cs{timechartsavey}, or to \(0\) if there has been no
%   use of \cs{timechartsavey} within the current \env{timechart} environment.
% \end{function}
%
% \begin{function}{\timechartsetyminimumautoreset, \timechartsetymaximumautoreset}
%   \begin{syntax}
%     \cs{timechartsetyminimumautoreset}\marg{min-coordinate}
%     \cs{timechartsetymaximumautoreset}\marg{max-coordinate}
%   \end{syntax}
%   Set \(y\) coordinates that automatically trigger \cs{timechartresety} if the current \(y\) coordinate goes below
%   \meta{min-coordinate} or above \meta{max-coordinate}.
% \end{function}
%
% \begin{function}{\timechartstepy}
%   \begin{syntax}
%     \cs{timechartstepy}\oarg{count}
%   \end{syntax}
%   Manually step the current \(y\) coordinate by \meta{count} times the value of \key{/timechart/ystep}. The default
%   value of \meta{count} is 1. (The \key{/timechart/no autostep} does not affect \cs{timechartstepy}.)
% \end{function}
%
%
%
% \subsection{Completion}
%
% \begin{function}{\timechartfinish}
%   Signal that the chart is complete and that the grid and axis should be drawn (unless the keys \key{/timechart/no
%   grid} and/or \key{/timechart/no axis} have been used). It is not necessary to use this command: if it is not given,
%   the grid and axis will be drawn at the end of the \env{timechart} environment. But after this command, the \TikZ\
%   nodes \texttt{grid} and \texttt{axis} are available, containing (respectively) the grid and the axis. These can be
%   used in for further \TikZ\ drawing.
%
%   Note that after \cs{timechartfinish}, none of the various \cs{timechart}\ldots\ commands are available inside that
%   \env{timechart} environment.
% \end{function}
%
%
%
% \subsection{Shortcut keys}
%
% \begin{describekey}{/timechart/left}{}{}
%   Equivalent to setting \key{/timechart/interval label pos} and \key{/timechart/text pos} to \val{left}.
% \end{describekey}
%
% \begin{describekey}{/timechart/center}{}{}
%   Equivalent to setting \key{/timechart/interval label pos} and \key{/timechart/text pos} to \val{center}.
% \end{describekey}
%
% \begin{describekey}{/timechart/right}{}{}
%   Equivalent to setting \key{/timechart/interval label pos} and \key{/timechart/text pos}{right} to \val{right}.
% \end{describekey}
%
%
%
% \section{Era indicators}
% \label{sec:era-indicators}
%
% \begin{function}{\timechartmakebeforeyear,\timechartmakeafteryear}
%   \begin{syntax}
%     \cs{timechartmakebeforeyear}\marg{number}
%     \cs{timechartmakeafteryear}\marg{number}
%   \end{syntax}
%   Typeset \meta{number} (which should be a positive whole number) as a year before or after the epoch. By default,
%   \cs{timechartmakebeforeyear}\marg{number} produces \timechartmakebeforeyear{\meta{number}} and
%   \cs{timechartmakeafteryear}\marg{number} produces \timechartmakeafteryear{\meta{number}}.
%
%   These commands are used for axis labels and can be re-defined by the user. For example, if \textsc{bc}/\textsc{ad}
%   is preferred to \textsc{bce}/\textsc{ce}, the user can define
% \iffalse
%<*example>
% \fi
\begin{lstlisting}
\renewcommand*{\timechartmakebeforeyear}[1]{#1~\textsc{bc}}
\renewcommand*{\timechartmakeafteryear}[1]{\textsc{ad}~#1}
\end{lstlisting}
% \iffalse
%</example>
% \fi
%   Similarly, if \textsc{ah}/\textsc{bh} is preferred, the user can define
% \iffalse
%<*example>
% \fi
\begin{lstlisting}
\renewcommand*{\timechartmakebeforeyear}[1]{#1~\textsc{bh}}
\renewcommand*{\timechartmakeafteryear}[1]{\textsc{ah}~#1}
\end{lstlisting}
% \iffalse
%</example>
% \fi
% \end{function}
%
%
%
% \section{Legend}
% \label{sec:keys}
%
% \pkg{timechart} supplies a number of auxiliary macros for creating a legend to explain, for example the significance
% of different colours of intervals. For example, \fullref{Figure}{fig:example1-legend} shows a suitable legend for
% \fullref{Figure}{fig:example1}.
%
% \begin{figure}[t]
%   \centering
%   \input{timechart-example1-legend.tex}
%   \caption{Example legend for the timechart shown in \fullref{Figure}{fig:example1}.}
%   \label{fig:example1-legend}
% \end{figure}
%
% The \cs{timechartlength}\ldots\ macros are \emph{not} meant to be used inside a \env{timechart} environment, but in
% locations such as running text or a \env{tabular} environment.
%
% \begin{function}{\timechartlegenditem}
%   \begin{syntax}
%     \cs{timechartlegenditem}\oarg{options}
%   \end{syntax}
%   Draw a bar suitable for use in a legend. \meta{options} specifies PGF keys that are applied within
%   \key{/timechart}. The same PGF keys that affect interval bars affect the drawn bar, as do the keys listed below.
% \end{function}
%
% \begin{function}{\timechartlegendstartrange, \timechartlegendfinishrange}
%   \begin{syntax}
%     \cs{timechartlegendstartrange}\oarg{options}
%     \cs{timechartlegendfinishrange}\oarg{options}
%   \end{syntax}
%   Draw a bar suitable for use in a legend, with a start or finish range. \meta{options} specifies PGF keys that are
%   applied within \key{/timechart/}. The same PGF keys that affect interval bars affect the drawn bar, as do the
%   keys listed below.
% \end{function}
%
% \begin{describekey}{/timechart/legend item width}{dimension}{9mm}
%   When using macros \cs{timechartlegenditem}, \cs{timechartlegendstartrange}, or \cs{timechartlegendfinishrange}, draw
%   a bar of total width \meta{dimension}.
% \end{describekey}
%
% \begin{describekey}{/timechart/legend item range width}{dimension}{3mm}
%   When using \cs{timechartlegendstartrange} or \cs{timechartlegendfinishrange}, draw a bar with a range of width
%   \meta{dimension}.
% \end{describekey}
%
%
%
% \section{Usage notes}
%
% \subsection{Additional \TikZ\ code}
%
% The \env{timechart} environment is a \env{tikzpicture}. The user can add any \TikZ\ code before, between, or after
% content created using the \cs{timechart}\ldots\ commands. Each use of \cs{timechartinterval} defines two nodes. One,
% by default named \val{bar node}, contains the interval bar; the other, by default named \val{label node}, contains the
% interval label. Similarly, text added using \cs{timecharttext} is contained in a node, by default named \val{text
% node}. (The default names are re-used, but can be changed using the keys \key{/timechart/interval bar node name},
% \key{/timechart/interval label node name}, and \key{/timechart/text node name}.) The user can use these nodes to
% position extra content.
%
% If the \cs{timechartfinish} command is used (after which the \cs{timechart}\ldots\ commands are no longer available
% within the \env{timechart} environment) the nodes \mcode{grid} and \mcode{axis}, which contain the grid and the axis,
% are also available.
%
%
%
% \subsection{\texorpdfstring{`year zero'}{year zero}}
% \label{subsec:year-zero}
%
% Although calendars typically do not admit a `year zero' (for instance, \timechartmakebeforeyear{1} is immediately
% followed by \timechartmakeafteryear{1}, with no intervening `year zero'), \pkg{timechart} does allow \val{0} for the
% \meta{start} or \meta{finish} of the \env{timechart} environment or as the \meta{start} or \meta{finish} of
% \cs{timechartinterval} or the \meta{year} of \cs{timecharttext}. But `year zero' is indicated on the axis by a special
% epoch marker showing the last year before and first year after the epoch.
%
%
%
% \section{Feature requests and bug reports}
%
% The development code and issue tracker are hosted at Codeberg: \url{https://codeberg.org/ajcain/timechart}
%
%
%
% \section{Appendix: full example source}
% \label{sec:full-example}
%
% This section contains the necessary source code to produce the example timechart and legend shown in
% \fullref{Figures}{fig:example1} and \ref{fig:example1-legend} on pages \pageref{fig:example1} and
% \pageref{fig:example1-legend}.
%
%
%
% \subsection{Setup source}
%
% \lstinputlisting{timechart-example1-setup.tex}
%
%
%
% \subsection{Timechart source}
%
% \lstinputlisting[breaklines=true]{timechart-example1-timechart.tex}
%
%
%
% \subsection{Legend source}
%
% \lstinputlisting{timechart-example1-legend.tex}
%
%
%
% \end{documentation}
%
%
%
% \iffalse
%<*example1-setup>
\pgfkeys{
  /timechart/.cd,
  julioclaudian/.style={
    interval bar color=red!70!black,
    interval mark color=red!70!black!50!white
  },
  fouremperors/.style={
    interval bar color=green!65!black,
    interval mark color=green!65!black!50!white
  },
  flavian/.style={
    interval bar color=yellow!85!black,
    interval mark color=yellow!85!black!50!white
  },
  nervaantonine/.style={
    interval bar color=blue!80!black,
    interval mark color=blue!80!black!50!white
  },
  fiveemperors/.style={
    interval bar color=green!50!black,
    interval mark color=green!50!black!50!white
  },
  severan/.style={
    interval bar color=orange!80!black,
    interval mark color=orange!80!black!50!white
  },
  thirdcentury/.style={
    interval bar color=green!35!black,
    interval mark color=green!35!black!50!white
  },
  tetrarchy/.style={
    interval bar color=purple!70!black,
    interval mark color=purple!70!black!50!white
  },
  constantinian/.style={
    interval bar color=blue!65!white,
    interval mark color=blue!65!white!50!white
  },
  valentinianic/.style={
    interval bar color=orange!60!black,
    interval mark color=orange!60!black!50!white
  },
  theodosian/.style={
    interval bar color=cyan,
    interval mark color=cyan!50!white
  },
  theodosian-east/.style={
    interval bar color=cyan!80!black,
    interval mark color=cyan!80!black!50!white
  },
  theodosian-west/.style={
    interval bar color=cyan!80!white,
    interval mark color=cyan!80!white!50!white
  },
  leonid/.style={
    interval bar color=purple!40!white,
    interval mark color=purple!40!white!50!white
  },
  justinian/.style={
    interval bar color=orange!60!white,
    interval mark color=orange!60!white!50!white
  },
  lastwest/.style={
    interval bar color=green!25!black,
    interval mark color=green!25!black!50!white
  },
}
%</example1-setup>
%<*example1-timechart>
\begin{timechart}[
    axis line/.append style={ draw=gray, line width=.5pt },
    grid/.append style={ draw=lightgray!50!white, line width=.5pt },
    minor tick/.append style={ draw=gray },
    major tick/.append style={ line width=.5pt, draw=gray },
    major tick label/.append style={ node font=\small },
    interval label/.style={ node font=\sffamily\footnotesize },
    text/.style={ node font=\sffamily\small\itshape, },
    ystep=-3.25mm,
  ]{-50}{500}

  \pgfmathsetmacro{\mainlinecount}{46}

  \timechartsetyminimumautoreset{-3.25mm*\mainlinecount+1mm}

  \timechartinterval[interval bar color=gray,right,mark=-45]{-100}{-44}{Julius Caesar}
  \timechartinterval[julioclaudian,right,mark=-27]{-63}{-14}{Augustus}
  \timechartinterval[julioclaudian,right,mark=14]{-42}{37}{Tiberius}
  \timechartinterval[julioclaudian,right,mark=37]{12}{41}{Caligula}
  \timechartinterval[julioclaudian,right,mark=41]{-10}{54}{Claudius}
  \timechartinterval[julioclaudian,right,mark=54]{37}{68}{Nero}

  \timechartinterval[fouremperors,mark=68]{-3}{69}{Galba}
  \timechartinterval[fouremperors,mark=69]{32}{69}{Otho}
  \timechartinterval[fouremperors,mark=69]{15}{69}{Vitellius}

  \timechartinterval[flavian,mark=69]{9}{79}{Vespasian}
  \timechartinterval[flavian,mark=79]{39}{81}{Titus}
  \timechartinterval[flavian,mark=81]{51}{96}{Domitian}

  \timechartinterval[nervaantonine,mark=96]{30}{98}{Nerva}
  \timechartinterval[nervaantonine,mark=98]{53}{117}{Trajan}
  \timechartinterval[nervaantonine,mark=117]{76}{138}{Hadrian}
  \timechartinterval[nervaantonine,mark=138]{86}{161}{Antoninus Pius}
  \timechartinterval[nervaantonine,mark=161]{121}{180}{Marcus Aurelius}
  \timechartinterval[nervaantonine,mark=161]{130}{169}{Lucius Verus}
  \timechartinterval[nervaantonine,mark=180]{161}{192}{Commodus}

  \timechartinterval[fiveemperors,mark=193]{126}{193}{Pertinax}
  \timechartinterval[fiveemperors,mark=193]{133}{193}{Didius Julianus}

  \timechartinterval[severan,mark=193]{145}{211}{Septimus Severus}
  \timechartinterval[severan,mark=211]{188}{217}{Caracalla}
  \timechartinterval[severan,mark=211]{189}{211}{Geta}
  \timechartinterval[severan,mark=217]{c165}{218}{Macrinus}
  \timechartinterval[severan,mark=218]{203/204}{222}{Elagabalus}
  \timechartinterval[severan,mark=222]{208}{235}{Severus Alexander}

  \timechartinterval[thirdcentury,mark=235]{c172/c180}{238}{Maximinus I}
  \timechartinterval[thirdcentury,mark=238]{c158}{238}{Gordian I}
  \timechartinterval[thirdcentury,mark=238]{192}{238}{Gordian II}
  \timechartinterval[thirdcentury,mark=238]{164}{238}{Pupienus}
  \timechartinterval[thirdcentury,mark=238]{c164}{238}{Balbinus}
  \timechartinterval[thirdcentury,mark=238]{225}{244}{Gordian III}
  \timechartinterval[thirdcentury,mark=244]{c204}{249}{Philip I}
  \timechartinterval[thirdcentury,mark=249]{c190/200}{251}{Decius}
  \timechartinterval[thirdcentury,mark=251]{c206}{253}{Trebonianus Gallus}
  \timechartinterval[thirdcentury,mark=253]{c207}{253}{Aemilianus}
  \timechartinterval[thirdcentury,mark=253]{c200}{262}{Valerian}
  \timechartinterval[thirdcentury,mark=253]{218}{268}{Gallienus}
  \timechartinterval[thirdcentury,mark=268]{214}{270}{Claudius II}
  \timechartinterval[thirdcentury,mark=270]{230/250}{270}{Quintillus}
  \timechartinterval[thirdcentury,mark=270]{214}{275}{Aurelian}
  \timechartinterval[thirdcentury,mark=275]{c200}{276}{Tacitus}
  \timechartinterval[thirdcentury,mark=276]{226/256}{276}{Florianus}
  \timechartinterval[thirdcentury,mark=276]{232}{282}{Probus}
  \timechartinterval[thirdcentury,mark=282]{c224}{283}{Carus}
  \timechartinterval[thirdcentury,mark=283]{c250}{285}{Carinus}
  \timechartinterval[thirdcentury,mark=283]{c253}{284}{Numerian}

  \timechartinterval[tetrarchy,mark=284]{242/245}{311/312}{Diocletian}
  \timechartinterval[tetrarchy,mark=286]{c250}{310}{Maximian}
  \timechartinterval[tetrarchy,mark=305]{c258}{311}{Galerius}
  \timechartinterval[tetrarchy,mark=305]{c250}{306}{Constantius I}
  \timechartinterval[tetrarchy,mark=306]{257/287}{307}{Severus II}
  \timechartinterval[tetrarchy,marks={308,324}]{c265}{325}{Licinius}
  \timechartinterval[tetrarchy,mark=310]{c270}{313}{Maximinus II}
  \timechartinterval[tetrarchy,mark=316]{267/297}{317}{Valerius Valens}
  \timechartinterval[tetrarchy,mark=324]{275/305}{325}{Martinian}

  \timechartinterval[constantinian,mark=306]{272/273}{337}{Constantine I}
  \timechartinterval[constantinian,mark=337]{316}{340}{Constantine II}
  \timechartinterval[constantinian,mark=337]{322/323}{350}{Constans I}
  \timechartinterval[constantinian,mark=337]{317}{361}{Constantius II}
  \timechartinterval[constantinian,mark=361]{331}{363}{Julian}
  \timechartinterval[constantinian,mark=363]{330/331}{364}{Jovian}

  \timechartinterval[valentinianic,mark=364]{321}{375}{Valentinian I}
  \timechartinterval[valentinianic,mark=364]{c328}{378}{Valens}
  \timechartinterval[valentinianic,mark=375]{359}{383}{Gratian}
  \timechartinterval[valentinianic,mark=388]{371}{392}{Valentinian II}

  \timechartinterval[theodosian,mark=379]{346/347}{395}{Theodosius I}
  \timecharttext[center]{395}{Eastern}
  \timechartinterval[theodosian-east,mark=395]{377}{408}{Arcadius}
  \timechartinterval[theodosian-east,mark=408]{401}{450}{Theodosius II}
  \timechartinterval[theodosian-east,mark=450]{391/392}{457}{Marcian}

  \timechartinterval[leonid,mark=457]{400/401}{474}{Leo I}
  \timechartinterval[leonid,mark=474]{467}{474}{Leo II}
  \timechartinterval[leonid,mark={474,475,476}]{425}{491}{Zeno}
  \timechartinterval[leonid,mark=475]{426/456}{476/477}{Basilicus}
  \timechartinterval[leonid,mark=491]{430/431}{518}{Anastasius I}

  \timechartinterval[justinian,mark=518]{450}{527}{Justin I}
  \timechartinterval[justinian,mark=527]{482}{565}{Justinian I}

  \timecharttext[center]{395}{Western}
  \timechartinterval[theodosian-west,mark=395]{384}{423}{Honorius}
  \timechartinterval[theodosian-west,mark=421]{371/401}{421}{Constantius III}
  \timechartinterval[theodosian-west,mark=425]{419}{455}{Valentian III}

  \timechartinterval[lastwest,mark=455]{405/435}{455}{Petronius Maximus}
  \timechartinterval[lastwest,mark=455]{406/436}{456/457}{Avitius}
  \timechartinterval[lastwest,mark=457]{411/441}{461}{Majorian}
  \timechartinterval[lastwest,mark=461]{415/445}{465}{Libius Severus}
  \timechartinterval[lastwest,mark=467]{422/452}{472}{Anthemius}
  \timechartinterval[lastwest,mark=472]{422/452}{472}{Olybrius}
  \timechartinterval[lastwest,mark={473,474}]{443/473}{474/504}{Glycerius}
  \timechartinterval[lastwest,mark={474,465}]{430/460}{480}{Julius Nepos}
  \timechartinterval[lastwest,mark={475,476}]{c465}{507/527}{Romulus}

  \timechartsetyminimumautoreset{-\maxdimen}
  \timechartsety{(-\mainlinecount-1)*3.25mm}

  \timechartinterval[
    center,
    interval bar color=darkgray,
    interval text/.append style={ text=white },
    interval bar thickness=6.5mm
  ]{-509}{-27}{}
  \timechartstepy[-1]
  \timechartinterval[
    center,
    interval bar color=black,
    interval text/.append style={ node font=\sffamily\normalsize,text=white },
    interval bar thickness=6.5mm
  ]{-27}{395}{Roman Empire}
  \timechartstepy[-1.5]
  \timechartinterval[
    center,
    interval bar color=lightgray,
    interval bar thickness=3.25mm
  ]{395}{1453}{Eastern}
  \timechartinterval[
    center,
    interval bar color=gray,
    interval bar thickness=3.25mm
  ]{395}{476}{Western}
\end{timechart}
%</example1-timechart>
%<*example1-legend>
\begin{tabular}{rl}
  \timechartlegenditem[julioclaudian]   & Julio-Claudian dynasty      \\
  \timechartlegenditem[fouremperors]    & Year of four emperors       \\
  \timechartlegenditem[flavian]         & Flavian dynasty             \\
  \timechartlegenditem[nervaantonine]   & Nerva-Antonine dynasty      \\
  \timechartlegenditem[fiveemperors]    & Year of five emperors       \\
  \timechartlegenditem[severan]         & Severan dynasty             \\
  \timechartlegenditem[thirdcentury]    & Crisis of the third century \\
  \timechartlegenditem[tetrarchy]       & Tetrarchy                   \\
  \timechartlegenditem[constantinian]   & Constantinian dynasty       \\
  \timechartlegenditem[valentinianic]   & Valentinianic dynasty       \\
  \timechartlegenditem[theodosian]      & Theodosian dynasty          \\
  \timechartlegenditem[theodosian-east] & --- in the east             \\
  \timechartlegenditem[theodosian-west] & --- in the west             \\
  \timechartlegenditem[leonid]          & Leonid dynasty              \\
  \timechartlegenditem[justinian]       & Justinian dynasty           \\
  \timechartlegenditem[lastwest]        & Last emperors in the west   \\
\end{tabular}
%</example1-legend>
%<*example2-v1>
\begin{timechart}{-50}{75}
  \timechartinterval{-63}{-14}{Augustus}
  \timechartinterval{-42}{37}{Tiberius}
  \timechartinterval{12}{41}{Caligula}
  \timechartinterval{-10}{54}{Claudius}
  \timechartinterval{37}{68}{Nero}
\end{timechart}
%</example2-v1>
%<*example2-v2>
\begin{timechart}[
    minor tick interval=5,
    major tick interval=25,
    grid/.append style={ draw=lightgray },
    axis line/.append style={ draw=gray },
    minor tick/.append style={ draw=gray },
    major tick/.append style={ draw=gray },
    interval label/.append style={ node font=\sffamily\small },
    julioclaudian/.style={ interval bar color=red!80!black },
  ]{-50}{75}
  \timechartinterval[right,julioclaudian]{-63}{-14}{Augustus}
  \timechartinterval[right,julioclaudian]{-42}{37}{Tiberius}
  \timechartinterval[julioclaudian]{12}{41}{Caligula}
  \timechartinterval[julioclaudian]{-10}{54}{Claudius}
  \timechartinterval[julioclaudian]{37}{68}{Nero}
\end{timechart}
%</example2-v2>
% \fi
%
%
%
% \begin{implementation}
%
% \setcounter{secnumdepth}{7}
%
%
%
% \section{Implementation}
%
%    \begin{macrocode}
%<*package>
%<@@=timechart>
%    \end{macrocode}
%
%
%
% \subsection{Coding standard}
%
% This package makes extensive use of \pkg{pgfmath} computations. The usual \pkg{expl3} standard of ending variables
% with a type indicator (\texttt{\_bool}, \texttt{\_int}, etc.) is therefore adapted as follows:
% \begin{itemize}
%   \item[\texttt{\_year}] Stores a year, which could in principle be fractional.
%     \item[\texttt{\_pgf}] Stores a length calculated by \pkg{pgfmath}. (Unlike \texttt{\_dim}, there is no underlying
%           dimension register.)
%   \item[\texttt{\_x}] Stores a raw \(x\) coordinate (not in \TikZ's XY-coordinate system).
%   \item[\texttt{\_y}] Stores a raw \(y\) coordinate (not in \TikZ's XY-coordinate system).
%   \item[\texttt{\_text}] Stores text (not an \pkg{expl3} string).
% \end{itemize}
%
%
%
% \subsection{Initial set-up}
%
% Package identification/version information.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}[2020-02-02]
\ProvidesExplPackage{timechart}{2026-07-10}{0.57.1}
  {Typesetting chronological charts}
%    \end{macrocode}
%
%
%
% \subsection{Debugging macro}
%
% \begin{macro}{\@@_debug:n,\@@_debug_real:n}
%   Macro to output (many) debugging messages.
%    \begin{macrocode}
\cs_new:Npn \@@_debug_real:n #1
  {
    \typeout{timechart:~#1}
  }
\cs_set_eq:NN\@@_debug:n\use_none:n
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Load TikZ}
%
%    \begin{macrocode}
\RequirePackage{tikz}
%    \end{macrocode}
% In the remainder of the package, only a limited subset of \TikZ\ is used, and PGF code is preferred. For PGF keys, it
% is necessary to use \texttt{\textasciitilde} in place of a space.
%
%
%
% \subsection{Scratch variables}
%
% \begin{macro}{\l_@@_tmpa_bool,\l_@@_tmpb_bool,\l_@@_tmpc_bool,\l_@@_tmpd_bool}
%   Scratch boolean variables.
%    \begin{macrocode}
\bool_new:N\l_@@_tmpa_bool
\bool_new:N\l_@@_tmpb_bool
\bool_new:N\l_@@_tmpc_bool
\bool_new:N\l_@@_tmpd_bool
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_tmpa_dim,\l_@@_tmpb_dim,\l_@@_tmpc_dim,\l_@@_tmpd_dim}
%   Scratch dimension variables, reusing \cs{l_tmpa_dim} and \cs{l_tmpb_dim} with uniform names.
%    \begin{macrocode}
\cs_set_eq:NN\l_@@_tmpa_dim\l_tmpa_dim
\cs_set_eq:NN\l_@@_tmpb_dim\l_tmpb_dim
\dim_new:N\l_@@_tmpc_dim
\dim_new:N\l_@@_tmpd_dim
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Generic auxiliary functions}
%
% \begin{macro}{\@@_make_ref:NN}
%   Make hyperreference from text, if the supplied target is non-empty.
%   \begin{arguments}
%     \item Reference for hyperlink target, or empty.
%     \item Text.
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn\@@_make_ref:NN #1#2
  {
    \str_if_empty:NTF #1
      { #2 }
      { \hyperref[#1]{#2} }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{PGF auxiliary functions}
%
% \begin{macro}{@@_pgfmathsetbool:nn}
%   Set an \pkg{expl3} boolean variable to the outcome of a \pkg{pgfmath} comparison. This macro is simply a wrapper
%   around \cs{pgfmathsetmacro} using \mcode{ifthenelse} and returning the boolean literal true or false.
%    \begin{macrocode}
\cs_new:Npn\@@_pgfmathsetbool:nn #1#2
  {
    \pgfmathsetmacro{#1}{ifthenelse(#2,"\c_true_bool","\c_false_bool")}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_if_equal:nnF}%
%   Use \pkg{pgfmath} to check whether \param{1} and \param{2} are equal. If not, execute \param{3}.
%    \begin{macrocode}
\cs_new:Npn\@@_if_equal:nnF #1#2#3
  {
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}{#1==#2}
    \bool_if:NF\l_@@_tmpa_bool{#3}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_pgfextractxy:nnn}
%   Extract coordinates of \param{3} (a PGF point) to dimension variables \param{1} and \param{2}. This macro simply
%   combines the functionality of \cs{pgfextractx} and \cs{pgfextracty}.
%    \begin{macrocode}
\cs_new:Npn\@@_pgfextractxy:nnn #1#2#3
  {
    \pgf@process{#3}
    #1=\pgf@x\relax
    #2=\pgf@y\relax
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_hsmash_pgfnode:nnnnn}
%   Do the same as \cs{pgfnode} but only update the bounding box `vertically'.
%    \begin{macrocode}
\cs_new:Npn\@@_hsmash_pgfnode:nnnnn #1#2#3#4#5
  {
    \pgfinterruptboundingbox
    \pgfnode{#1}{#2}{#3}{#4}{#5}
    \pgfcoordinate
      {@@_tmpa_coord}
      {\pgfpointanchor{current~bounding~box}{south}}
    \pgfcoordinate
      {@@_tmpb_coord}
      {\pgfpointanchor{current~bounding~box}{north}}
    \endpgfinterruptboundingbox
    \pgfextractx
      {\l_@@_tmpa_dim}
      {\pgfpointanchor{@@_tmpa_coord}{center}}
    \pgfextractx
      {\l_@@_tmpb_dim}
      {\pgfpointanchor{@@_tmpb_coord}{center}}
    \pgfpathmoveto{\pgfpoint{\l_@@_tmpa_dim}{0}}
    \pgfpathmoveto{\pgfpoint{\l_@@_tmpb_dim}{0}}
    \pgfusepath{discard}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_make_rectangle_node:nnnn}
%   Make a node with south west corner \param{1}, north east corner \param{2}, and name \param{3}. \param{1} and
%   \param{2} should be given as PGF points. \param{4} is a boolean literal indicating whether the path should be
%   stroked.
%    \begin{macrocode}
\cs_new:Npn\@@_make_rectangle_node:nnnn #1#2#3#4
  {
    \group_begin:
    \@@_pgfextractxy:nnn
      {\l_@@_tmpa_dim}{\l_@@_tmpb_dim}{#1}
    \@@_pgfextractxy:nnn
      {\l_@@_tmpc_dim}{\l_@@_tmpd_dim}{#2}
    \pgftransformshift{#1}
    \pgfset{
      minimum~width=\l_@@_tmpc_dim-\l_@@_tmpa_dim,
      minimum~height=\l_@@_tmpd_dim-\l_@@_tmpb_dim,
      inner~sep=0,
      outer~sep=0,
    }
    \bool_if:NTF #4
      { \pgfnode{rectangle}{south~west}{}{#3}{\pgfusepath{draw}} }
      { \pgfnode{rectangle}{south~west}{}{#3}{\pgfusepath{discard}} }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_set_style_line_width:nn}
%   Set macro \param{1} to be the line width set by the PGF style \param{2}. Note that \cs{begingroup} and \cs{endgroup}
%   are used here because of the definition of \cs{pgfmathsmuggle}.
%    \begin{macrocode}
\cs_new:Npn\@@_set_style_line_width:nn #1#2
  {
    \begingroup
    \tikzset{#2}
    \pgfmathsetlengthmacro{#1}{\pgflinewidth}
    \pgfmathsmuggle #1
    \endgroup
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{PGF keys}
%
% All PGF keys for this package are under \key{/timechart/}.
%    \begin{macrocode}
\pgfkeys{
  /timechart/.cd,
%    \end{macrocode}
% Keys applicable to debugging.
%    \begin{macrocode}
  debug/.code = {
    \cs_set_eq:NN\@@_debug:n\@@_debug_real:n
  },
  no~debug/.code = {
    \cs_set_eq:NN\@@_debug:n\use_none:n
  },
%    \end{macrocode}
% Keys for tagging.
%    \begin{macrocode}
  alt/.forward~to = /tikz/alt,
  actualtext/.forward~to = /tikz/actualtext,
  artifact/.forward~to = /tikz/artifact,
  tagging-setup/.forward~to = /tikz/tagging-setup,
%    \end{macrocode}
% Keys applicable to whole chart.
%    \begin{macrocode}
  width/.initial=\textwidth,
  ystep/.initial=-10pt,
  minor~tick~interval/.initial=10,
  major~tick~interval/.initial=50,
  tolerance~start/.initial=5pt,
  tolerance~finish/.initial=5pt,
  beyond~length~start/.initial=5pt,
  beyond~length~finish/.initial=5pt,
  beyond~x~radius~start/.initial=4pt,
  beyond~x~radius~finish/.initial=4pt,
%    \end{macrocode}
% Shortcuts for tolerance and `beyond' indicators.
%    \begin{macrocode}
  tolerance/.code = {
    \pgfkeyssetvalue{/timechart/tolerance~start}{#1}
    \pgfkeyssetvalue{/timechart/tolerance~finish}{#1}
  },
  beyond~length/.code = {
    \pgfkeyssetvalue{/timechart/beyond~length~start}{#1}
    \pgfkeyssetvalue{/timechart/beyond~length~finish}{#1}
  },
  beyond~x~radius/.code = {
    \pgfkeyssetvalue{/timechart/beyond~x~radius~start}{#1}
    \pgfkeyssetvalue{/timechart/beyond~x~radius~finish}{#1}
  },
%    \end{macrocode}
% Keys applicable to the grid.
%    \begin{macrocode}
  no~grid/.code = { \bool_set_false:N\l_@@_grid_bool },
  grid~top~ysep/.initial={3pt},
  grid~bottom~ysep/.initial={3pt},
  grid/.style={},
%    \end{macrocode}
% Keys applicable to the axis.
%    \begin{macrocode}
  axis~line/.style={
    line~cap=rect,
  },
  axis~ysep/.initial=3pt,
  axis/.is~choice,
  axis/none/.code
    = { \int_set:Nn\l_@@_axis_int{0} },
  axis/above/.code
    = { \int_set:Nn\l_@@_axis_int{1} },
  axis/below/.code
    = { \int_set:Nn\l_@@_axis_int{2} },
  no~axis/.code = { \int_set:Nn\l_@@_axis_int{0} },
  minor~tick/.style={},
  minor~tick~length/.initial=1.5mm,
  major~tick/.style={},
  major~tick~length/.initial=3mm,
  major~tick~label/.style={
    inner~sep=0,
    outer~sep=0,
    anchor=mid~west,
    rotate=90,
  },
  major~tick~eras/.is~choice,
  major~tick~eras/none/.code
    = { \int_set:Nn\l_@@_major_tick_eras_int{0} },
  major~tick~eras/all/.code
    = { \int_set:Nn\l_@@_major_tick_eras_int{1} },
  major~tick~eras/outer/.code
    = { \int_set:Nn\l_@@_major_tick_eras_int{2} },
%    \end{macrocode}
% Keys applicable to intervals, texts, spaces, and legends.
%    \begin{macrocode}
  no~autostep/.code = { \bool_set_false:Nz\l_@@_autostep_bool },
  ref/.initial={},
  mark/.initial={},
  marks/.forward~to=/timechart/mark,
  circa~uncertainty/.initial=3,
  interval~minimum~width/.initial=1pt,
  interval~bar~color/.initial=black,
  interval~bar~thickness/.initial=8pt,
  interval~bar~node~name/.initial = {bar~node},
  interval~mark~color/.initial=gray,
  interval~label/.style={},
  interval~label~centered/.style={/timechart/interval~label,text=white},
  interval~label~centered~background/.style={/timechart/interval~label},
  interval~label~baseline/.initial=-3pt,
  interval~label~pos/.is~choice,
  interval~label~pos/left/.code
    = { \int_set:Nn\l_@@_label_pos_int{0} },
  interval~label~pos/center/.code
    = { \int_set:Nn\l_@@_label_pos_int{1} },
  interval~label~pos/right/.code
    = { \int_set:Nn\l_@@_label_pos_int{2} },
  interval~label~node~name/.initial = {label~node},
  start~range/.is~choice,
  start~range/fade/.code
    = { \int_set:Nn\l_@@_start_range_type_int{0} },
  start~range/slant/.code
    = { \int_set:Nn\l_@@_start_range_type_int{1} },
  finish~range/.is~choice,
  finish~range/fade/.code
    = { \int_set:Nn\l_@@_finish_range_type_int{0} },
  finish~range/slant/.code
    = { \int_set:Nn\l_@@_finish_range_type_int{1} },
%    \end{macrocode}
% Keys applicable only to texts.
%    \begin{macrocode}
  text~node~name/.initial = {text~node},
  text/.style={},
  text~baseline/.initial=-3pt,
  text~pos/.is~choice,
  text~pos/left/.code = { \int_set:Nn\l_@@_text_pos_int{0} },
  text~pos/center/.code = { \int_set:Nn\l_@@_text_pos_int{1} },
  text~pos/right/.code = { \int_set:Nn\l_@@_text_pos_int{2} },
%    \end{macrocode}
% Keys applicable only to legends.
%    \begin{macrocode}
  legend~item~width/.initial=9mm,
  legend~item~range~width/.initial=3mm,
%    \end{macrocode}
% Shortcuts for positioning.
%    \begin{macrocode}
  left/.code = {
    \int_set:Nn\l_@@_label_pos_int{0}
    \int_set:Nn\l_@@_text_pos_int{0}
  },
  center/.code = {
    \int_set:Nn\l_@@_label_pos_int{1}
    \int_set:Nn\l_@@_text_pos_int{1}
  },
  right/.code = {
    \int_set:Nn\l_@@_label_pos_int{2}
    \int_set:Nn\l_@@_text_pos_int{2}
  },
}
%    \end{macrocode}
%
% \begin{macro}{\l_@@_grid_bool}
%   Boolean indicating whether the grid will be drawn. This variable is by default true but can be set false via the
%   \key{/timechart/no grid} PGF key.
%    \begin{macrocode}
\bool_new:N\l_@@_grid_bool
\bool_set_true:N\l_@@_grid_bool
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_axis_int}
%   An integer indicating whether and where the axis will be drawn. This is set via the \key{/timechart/axis} PGF
%   key.
%    \begin{macrocode}
\int_new:N\l_@@_axis_int
\int_set:Nn\l_@@_axis_int{1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_major_tick_eras_int}
%   An integer indicating which major ticks will have era indicators. This is set via the \key{/timechart/major tick
%   era} PGF key.
%    \begin{macrocode}
\int_new:N\l_@@_major_tick_eras_int
\int_set:Nn\l_@@_major_tick_eras_int{2}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_autostep_bool}
%   Boolean indicating whether to automatically step the \(y\) coordinate after an interval, text, or space. This
%   variable is by default true but can be set false via the \key{/timechart/no autostep} PGF key.
%    \begin{macrocode}
\bool_new:N\l_@@_autostep_bool
\bool_set_true:N\l_@@_autostep_bool
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_label_pos_int}
%   An integer to hold the interval label position. This is set via the \key{/timechart/interval label pos} PGF key.
%    \begin{macrocode}
\int_new:N \l_@@_label_pos_int
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_text_pos_int}
%   An integer to hold the text position. This is set via the \key{/timechart/text pos} PGF key.
%    \begin{macrocode}
\int_new:N \l_@@_text_pos_int
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_start_range_type_int,\l_@@_finish_range_type_int}
%   Integers to hold the type of the start/end ranges. These are set via the \key{/timechart/start range} and
%   \key{/timechart/finish range} PGF keys.
%    \begin{macrocode}
\int_new:N \l_@@_start_range_type_int
\int_new:N \l_@@_finish_range_type_int
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Main environment}
%
% \begin{macro}{timechart}
%   The main environment.
%   \begin{arguments}
%     \item PGF keys to apply.
%     \item Start year.
%     \item End year.
%   \end{arguments}
%    \begin{macrocode}
\NewDocumentEnvironment{timechart}{ O{} m m }
  { \@@_main_begin:nnn{#1}{#2}{#3} }
  { \@@_main_end: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_main_begin:nnn}
%   This command uses values specified by PGF keys to make some necessary calculations to begin the chart.
%    \begin{macrocode}
\cs_new:Npn \@@_main_begin:nnn #1#2#3
  {
%    \end{macrocode}
%   Process the supplied PGF keys and retrieve values that affect the chart as a whole.
%    \begin{macrocode}
    \pgfkeys{
      /timechart/.cd,
      #1,
      width/.get=\l_@@_width_pgf,
      ystep/.get=\l_@@_ystep_pgf,
      grid~top~ysep/.get=\l_@@_grid_top_ysep_pgf,
      grid~bottom~ysep/.get=\l_@@_grid_bottom_ysep_pgf,
      minor~tick~interval/.get=\l_@@_minor_tick_interval_year,
      major~tick~interval/.get=\l_@@_major_tick_interval_year,
    }
%    \end{macrocode}
%   Start the \TikZ\ picture and set up the necessary layers.
%    \begin{macrocode}
    \tikzpicture
    \pgfdeclarelayer{grid}
    \pgfdeclarelayer{labelbg}
    \pgfsetlayers{grid,labelbg,main}
%    \end{macrocode}
%   Store the line width of the grid and axis, treating them as \qty{0}{\point} if they are disabled.
%    \begin{macrocode}
    \bool_if:NTF\l_@@_grid_bool
      {
        \@@_set_style_line_width:nn
          {\l_@@_grid_line_width}
          {/timechart/grid}
      }
      { \pgfmathsetlengthmacro{\l_@@_grid_line_width}{0} }
    \int_if_zero:nTF{ \l_@@_axis_int }
      {
        \pgfmathsetlengthmacro{\l_@@_axis_line_width}{0}
        \pgfmathsetlengthmacro{\l_@@_major_tick_line_width}{0}
        \pgfmathsetlengthmacro{\l_@@_minor_tick_line_width}{0}
      }
      {
        \@@_set_style_line_width:nn
          {\l_@@_axis_line_width}
          {/timechart/axis~line}
        \@@_set_style_line_width:nn
          {\l_@@_major_tick_line_width}
          {/timechart/major~tick}
        \@@_set_style_line_width:nn
          {\l_@@_minor_tick_line_width}
          {/timechart/minor~tick}
      }
%    \end{macrocode}
%   Store the start and finish years (ignoring circa, month, day), and then set up the conversion from years to \(x\)
%   coordinates. \cs{l_@@_x} is the \(x\)-distance corresponding to one year, and \mcode{yeartox} is the \pkg{pgfmath}
%   function that does the conversion.
%    \begin{macrocode}
    \@@_parse_date:NNn\l_tmpa_bool\l_@@_start_year{#2}
    \@@_parse_date:NNn\l_tmpa_bool\l_@@_finish_year{#3}
    \pgfmathsetmacro{\l_@@_start_year}
      {floor(\l_@@_start_year)}
    \pgfmathsetmacro{\l_@@_finish_year}
      {floor(\l_@@_finish_year)}
    \pgfmathsetmacro{\l_@@_x}
      {
        (
          \l_@@_width_pgf
          - max(
            \l_@@_grid_line_width,
            \l_@@_axis_line_width,
            \l_@@_major_tick_line_width,
            \l_@@_minor_tick_line_width
          )
        )/(\l_@@_finish_year-\l_@@_start_year)
      }
    \pgfkeys{
      /pgf/declare~function={
        yeartox(\n)=\l_@@_x*(\n-\l_@@_start_year);
      },
    }
%    \end{macrocode}
% Calculate the start and finish \(x\) coordinates.
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_start_x}
      {yeartox(\l_@@_start_year)}
    \pgfmathsetmacro{\l_@@_finish_x}
      {yeartox(\l_@@_finish_year)}
%    \end{macrocode}
% Set up tracking of current \(y\) coordinate.
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_current_y}{0}
    \pgfmathsetmacro{\l_@@_saved_y}{0}
    \pgfmathsetmacro{\l_@@_auto_reset_minimum_y}{-16000pt}
    \pgfmathsetmacro{\l_@@_auto_reset_maximum_y}{16000pt}
%    \end{macrocode}
% Calculate some years used in loops.
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_start_plus_year}{
      \l_@@_start_year+\l_@@_minor_tick_interval_year
    }
    \pgfmathsetmacro{\l_@@_start_plusplus_year}{
      \l_@@_start_year+(2*\l_@@_minor_tick_interval_year)
    }
    \pgfmathsetmacro{\l_@@_end_minus_year}{
      \l_@@_finish_year-\l_@@_minor_tick_interval_year
    }
%    \end{macrocode}
%   Begin a group and make available the user commands \cs{timechart}\ldots. (The group will be ended by
%   \cs{@@_main_end_user:}.)
%    \begin{macrocode}
    \group_begin:
    \cs_set_eq:NN\timechartinterval\@@_interval_user:Ommm
    \cs_set_eq:NN\timecharttext\@@_text_user:Omm
    \cs_set_eq:NN\timechartspace\@@_space_user:O
    \cs_set_eq:NN\timechartsety\@@_set_y_user:m
    \cs_set_eq:NN\timechartsavey\@@_save_y_user:
    \cs_set_eq:NN\timechartresety\@@_reset_y_user:
    \cs_set_eq:NN\timechartsetyminimumautoreset
      \@@_set_y_minimum_auto_reset_user:m
    \cs_set_eq:NN\timechartsetymaximumautoreset
      \@@_set_y_maximum_auto_reset_user:m
    \cs_set_eq:NN\timechartstepy\@@_step_y_user:O
    \cs_set_eq:NN\timechartfinish\@@_main_end_user:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_main_end:}
%   Make sure the chart is complete and end the \TikZ\ picture. \cs{@@_main_end_user:} ends the group begun by
%   \cs{@@_main_begin:nnn}, so whether the user has \emph{not} called it (as \cs{timechartfinish}) is equivalent to it
%   being equal to \cs{timechartfinish}.
%    \begin{macrocode}
\cs_new:Npn\@@_main_end:
  {
    \cs_if_eq:NNT\timechartfinish\@@_main_end_user:
      { \@@_main_end_user: }
    \endtikzpicture
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_main_end_user:}
%   End the group begun by \cs{@@_main_begin:nnn}, draw the axis and grid, and set the bounding box. This macro is made
%   available as \cs{timechartfinish} inside the \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_main_end_user:
  {
%    \end{macrocode}
%   The aim here is to set the bounding box (1) to fit horizontally the axis \emph{not} including labels and the grid
%   and (2) to fit vertically the axis including labels and the grid . All the `horizonatal' data is already known, and
%   the `vertical' data is determined by the \emph{current} bounding box. So extract the `vertical' data and then reset
%   the bounding box.
%    \begin{macrocode}
    \pgfextracty{\l_@@_tmpa_dim}
      { \pgfpointanchor{current~bounding~box}{south} }
    \pgfextracty{\l_@@_tmpb_dim}
      { \pgfpointanchor{current~bounding~box}{north} }
    \pgfresetboundingbox
%    \end{macrocode}
%   If the timechart is empty, then the extracted \(y\) coordinates of `north' and `south' anchors of the bounding box
%   will be \qty{-16000}{\point} and \qty{16000}{\point} respectively. Test for this and treat them as both having \(y\)
%   coordinate \qty{0}{\point} in this case.
%    \begin{macrocode}
    \dim_compare:nNnTF{\l_@@_tmpa_dim}>{\l_@@_tmpb_dim}
      {
        \pgfmathsetmacro{\l_@@_content_bottom_y}{0pt}
        \pgfmathsetmacro{\l_@@_content_top_y}{0pt}
      }
      {
        \pgfmathsetmacro{\l_@@_content_bottom_y}
          {\l_@@_tmpa_dim}
        \pgfmathsetmacro{\l_@@_content_top_y}
          {\l_@@_tmpb_dim}
      }
%    \end{macrocode}
%   Now draw the grid and axis if necessary and set the bounding box if not.
%    \begin{macrocode}
    \bool_if:NTF{\l_@@_grid_bool}
      { \@@_grid_draw: }
      { \@@_nogrid_bounding_box_set: }
    \@@_axis_draw:
%    \end{macrocode}
%   Finally, end the group begun by \cs{@@_main_begin:nnn}.
%    \begin{macrocode}
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Grid drawing}
%
% \begin{macro}{\@@_grid_draw:}
%   Draw the grid of the chart, assuming that the \(y\) coordinates of the top and bottom of the content have been
%   calculated and stored in \cs{l_@@_content_top_y} and \cs{l_@@_content_bottom_y}. These variable will be updated to
%   the grid top and bottom.
%    \begin{macrocode}
\cs_new:Npn\@@_grid_draw:
  {
    \pgfmathsetmacro{\l_@@_content_bottom_y}{
      \l_@@_content_bottom_y-\l_@@_grid_bottom_ysep_pgf
    }
    \pgfmathsetmacro{\l_@@_content_top_y}{
      \l_@@_content_top_y+\l_@@_grid_top_ysep_pgf
    }
    \pgfonlayer{ grid }
    \scope[/timechart/grid]
    \foreach \year in {
      \l_@@_start_plus_year,
      \l_@@_start_plusplus_year,
      ...,
      \l_@@_end_minus_year
    } {
      \group_begin:
%    \end{macrocode}
%   Only draw gridlines at major ticks.
%    \begin{macrocode}
      \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
        { Mod(\year,\l_@@_major_tick_interval_year)==0 }
      \bool_if:NT\l_@@_tmpa_bool
        {
          \pgftransformshift{ \pgfpoint{yeartox(\year)}{0} }
          \pgfpathmoveto{ \pgfpoint{0}{\l_@@_content_top_y} }
          \pgfpathlineto{ \pgfpoint{0}{\l_@@_content_bottom_y} }
          \pgfusepath{ draw }
        }
      \group_end:
    }
%    \end{macrocode}
%   Define and draw the grid node.
%    \begin{macrocode}
    \@@_make_rectangle_node:nnnn
      { \pgfpoint{\l_@@_start_x}{\l_@@_content_bottom_y} }
      { \pgfpoint{\l_@@_finish_x}{\l_@@_content_top_y} }
      { grid }
      { \c_true_bool }
    \endscope
    \endpgfonlayer
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Axis drawing}
%
% \begin{macro}{\@@_axis_draw:}
%   Draw the axis, with large/small ticks and labels on appropriate years.
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw:
  {
    \group_begin:
    \int_case:nn{ \l_@@_axis_int }
    {
      {0}
      { \prg_do_nothing: }
      {1}
      {
        \pgftransformshift{
          \pgfpoint{0}{
            \l_@@_content_top_y
            +\pgfkeysvalueof{/timechart/axis~ysep}
          }
        }
        \pgfmathsetmacro{\l_@@_tick_orientation_pgf}{1}
        \cs_set:Npn\l_@@_tick_label_anchor_text
          { mid~west }
        \cs_set:Npn\l_@@_zero_tick_before_label_anchor_text
          { base~west }
        \cs_set:Npn\l_@@_zero_tick_after_label_anchor_text
          { north~west }
        \@@_axis_draw_aux:
      }
      {2}
      {
        \pgftransformshift{
          \pgfpoint{0}{
            \l_@@_content_bottom_y
            -\pgfkeysvalueof{/timechart/axis~ysep}
          }
        }
        \pgfmathsetmacro{\l_@@_tick_orientation_pgf}{-1}
        \cs_set:Npn\l_@@_tick_label_anchor_text
          { mid~east }
        \cs_set:Npn\l_@@_zero_tick_before_label_anchor_text
          { base~east }
        \cs_set:Npn\l_@@_zero_tick_after_label_anchor_text
          { north~east }
        \@@_axis_draw_aux:
      }
    }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_aux:}
%   Draw the axis, with large/small ticks and labels on appropriate years, assuming that the \(y\) coordinate has been
%   calculated and stored in \cs{l_@@_axis_y}.
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_aux:
  {
    \pgfkeys{
      /timechart/minor~tick~length/.get=\@@_minor_tick_length_pgf,
      /timechart/major~tick~length/.get=\@@_major_tick_length_pgf,
    }
%    \end{macrocode}
% Work out the first and last years which will have a major tick (since these are marked with the era).
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_start_major_tick_year}
      {
        \l_@@_start_year
        -Mod(
          \l_@@_start_year,
          \l_@@_major_tick_interval_year
        )
      }
    \pgfmathsetmacro{\l_@@_start_major_tick_year}
      {
        ifthenelse(
          \l_@@_start_major_tick_year<\l_@@_start_year,
          \l_@@_start_major_tick_year
            +\l_@@_major_tick_interval_year,
          \l_@@_start_major_tick_year
        )
      }
    \pgfmathsetmacro{\l_@@_start_plus_major_tick_year}
      {
        \l_@@_start_major_tick_year
        +\l_@@_major_tick_interval_year
      }
    \pgfmathsetmacro{\l_@@_finish_major_tick_year}
      {
        \l_@@_finish_year
        -Mod(
          \l_@@_finish_year,
          \l_@@_major_tick_interval_year
        )
      }
%    \end{macrocode}
% Loop over years and draw the minor ticks.
%    \begin{macrocode}
    \foreach \year in {
      \l_@@_start_year,
      \l_@@_start_plus_year,
      ...,
      \l_@@_finish_year
    } {
      \pgfmathsetmacro{\x}{yeartox(\year)}
      \@@_pgfmathsetbool:nn
        {\l_@@_tmpa_bool}
        {
          Mod(
            \year-\l_@@_start_major_tick_year,
            \l_@@_major_tick_interval_year
          )==0
        }
      \bool_if:NF\l_@@_tmpa_bool
        { \@@_axis_draw_minor_tick:N\x }
    }
%    \end{macrocode}
% Loop over years and draw the major ticks.
%    \begin{macrocode}
    \foreach \year in {
      \l_@@_start_major_tick_year,
      \l_@@_start_plus_major_tick_year,
      ...,
      \l_@@_finish_major_tick_year
    } {
      \pgfmathsetmacro{\x}{yeartox(\year)}
      \@@_axis_draw_labelled_major_tick:NN\x\year
    }
%    \end{macrocode}
% Define the axis line and define the axis node.
%    \begin{macrocode}
    \@@_draw_axis_line
    \int_case:nn{\l_@@_axis_int}
    {
      {1}
      {
        \pgfextracty{\l_@@_tmpa_dim}
          { \pgfpointanchor{current~bounding~box}{north} }
        \pgfmathsetmacro{\l_@@_axis_top_y}{\l_@@_tmpa_dim}
        \pgfmathsetmacro{\l_@@_axis_bottom_y}{0}
      }
      {2}
      {
        \pgfextracty{\l_@@_tmpa_dim}
          { \pgfpointanchor{current~bounding~box}{south} }
        \pgfmathsetmacro{\l_@@_axis_top_y}{0}
        \pgfmathsetmacro{\l_@@_axis_bottom_y}{\l_@@_tmpa_dim}
      }
    }
    \@@_make_rectangle_node:nnnn
      { \pgfpoint{\l_@@_start_x}{\l_@@_axis_bottom_y} }
      { \pgfpoint{\l_@@_finish_x}{\l_@@_axis_top_y} }
      { axis }
      { \c_false_bool }
  }
%    \end{macrocode}
% \end{macro}
%
% All the remaining axis-related macros (which begin \cs{@@_axis_draw_}) assume that a transformation has been applied
% so that the axis line is at \(y=0\).
%
% \begin{macro}{\@@_axis_draw_minor_tick:N}
%  Draw an unlabelled tick at \(x\) coordinate \param{1}.
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_minor_tick:N #1
  {
    \scope[/timechart/minor~tick]
    \pgfpathmoveto{ \pgfpoint{#1}{0} }
    \pgfpathlineto{
      \pgfpoint{#1}{
        \l_@@_tick_orientation_pgf
        *\@@_minor_tick_length_pgf
      }
    }
    \pgfusepath{draw}
    \endscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_labelled_major_tick:NN}
%   Draw a labelled major tick at \(x\) coordinate \param{1}, with label for year \param{2}, using the special epoch
%   marker if the year is 0, and showing the era if and only if the year is for the first or last major tick. This macro
%   assumes that \cs{@@_start_major_tick_year} and \cs{@@_finish_major_tick_year} have been calculated.
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_labelled_major_tick:NN #1#2
  {
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}{#2==0}
    \bool_if:NTF \l_@@_tmpa_bool
      { \@@_axis_draw_zero_tick:N #1 }
      {
        \int_case:nn { \l_@@_major_tick_eras_int }
        {
          {0}{ \bool_set_false:N\l_@@_tmpd_bool }
          {1}{ \bool_set_true:N\l_@@_tmpd_bool }
          {2}
          {
            \@@_pgfmathsetbool:nn{\l_@@_tmpb_bool}
              { #2==\l_@@_start_major_tick_year }
            \@@_pgfmathsetbool:nn{\l_@@_tmpc_bool}
              { #2==\l_@@_finish_major_tick_year }
            \bool_set:Nn\l_@@_tmpd_bool
              { \l_@@_tmpb_bool || \l_@@_tmpc_bool }
          }
        }
        \@@_axis_draw_major_tick:N #1
        \@@_axis_draw_year_label:nnnnnn
          { #1 }
          { #2 }
          { \l_@@_tmpd_bool }
          { \l_@@_tick_label_anchor_text }
          { 0 }
          {
            \l_@@_tick_orientation_pgf
            *(\@@_major_tick_length_pgf+1mm)
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_major_tick:N}
%  Draw a major tick at \(x\) coordinate \param{1}.
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_major_tick:N #1
  {
    \scope[/timechart/major~tick]
    \pgfpathmoveto{ \pgfpoint{#1}{0} }
    \pgfpathlineto{
      \pgfpoint{#1}{
        \l_@@_tick_orientation_pgf
        *\@@_major_tick_length_pgf
      }
    }
    \pgfusepath{draw}
    \endscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_zero_tick:N}
%  Draw a special (labelled) tick for year zero at \(x=\param{1}\).
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_zero_tick:N #1
  {
    \group_begin:
    \pgftransformshift{ \pgfpoint{#1}{0} }
%    \end{macrocode}
%   The mark is a cross made up of four arcs and the miter joins between them. The parameter \cs{r} is the arc radius.
%   The parameter \cs{a} is how many degrees should be trimmed from the start/end of a quarter-circle to form each arc.
%   Thus the length of the miter is dependent on \cs{a}.
%    \begin{macrocode}
    \pgfmathsetmacro{\a}{5}
    \pgfmathsetlengthmacro{\r}{1mm}
    \pgfmathsetlengthmacro{\t}{\r*(cos(\a)-cos(90-\a))/(1-cos(90-\a))}
%    \end{macrocode}
%   The drawing process is: move to the start of the tick, draw the tick, draw the four arcs, then draw a small part of
%   the tick again. The last step is not mathematically necessary for a smooth join, but ensures that the join
%   \emph{appears} smooth.
%    \begin{macrocode}
    \scope[/timechart/major~tick,line~join=miter]
    \group_begin:
    \pgftransformyscale{\l_@@_tick_orientation_pgf}
    \pgfpathmoveto{\pgfpointorigin}
    \pgfpathlineto{\pgfpoint{0}{\@@_major_tick_length_pgf}}
    \pgfpatharc{0}{90-\a}{\t~and~\r}
    \pgfpatharc{270+\a}{360-\a}{\r}
    \pgfpatharc{180+\a}{270-\a}{\r}
    \pgfpatharc{90+\a}{180-\a}{\t~and~\r}
    \pgfpathlineto{\pgfpoint{0}{\@@_major_tick_length_pgf-1pt}}
    \pgfusepath{draw}
    \group_end:
    \endscope
%    \end{macrocode}
%   There is no year 0, so label the zero mark with the 1 before and 1 after the epoch.
%    \begin{macrocode}
    \@@_axis_draw_year_label:nnnnnn
      { 0 }
      { -1 }
      { \c_true_bool }
      { \l_@@_zero_tick_before_label_anchor_text }
      { -.5mm }
      { \l_@@_tick_orientation_pgf*5.5mm }
    \@@_axis_draw_year_label:nnnnnn
      { 0 }
      { 1 }
      { \c_true_bool }
      { \l_@@_zero_tick_after_label_anchor_text }
      { .5mm }
      { \l_@@_tick_orientation_pgf*5.5mm }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_line}
%   Draw the axis line itself.
%    \begin{macrocode}
\cs_new:Npn\@@_draw_axis_line
  {
    \scope[/timechart/axis~line]
    \pgfpathmoveto{ \pgfpoint{\l_@@_start_x}{0} }
    \pgfpathlineto{ \pgfpoint{\l_@@_finish_x}{0} }
    \pgfusepath{draw}
    \endscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_axis_draw_year_label:nnnnnn}
%  Draw a year label.
%   \begin{arguments}
%     \item \(x\) coordinate.
%     \item Year for label.
%     \item Boolean literal indicating whether the era should be shown.
%     \item Anchor for node.
%     \item \(x\) offset (dimension).
%     \item \(y\) offset (dimension).
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn\@@_axis_draw_year_label:nnnnnn #1#2#3#4#5#6
  {
    \group_begin:
    \pgftransformshift{ \pgfpoint{#1+#5}{#6} }
    \pgfmathtruncatemacro{\absyear}{ abs(#2) }
    \scope[/timechart/major~tick~label]
    \bool_if:NTF #3
      {
        \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}{#2<0}
        \bool_if:NTF\l_@@_tmpa_bool
          { \cs_set_eq:NN\@@_make_year:n\timechartmakebeforeyear }
          { \cs_set_eq:NN\@@_make_year:n\timechartmakeafteryear  }
      }
      { \cs_set_eq:NN\@@_make_year:n\use:n }
    \@@_hsmash_pgfnode:nnnnn
      {rectangle}
      {#4}
      {\@@_make_year:n{\absyear}}
      {}
      {}
    \endscope
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\timechartmakebeforeyear,\timechartmakeafteryear}
%   User-redefineable macros to format a year as before or after the epoch.
%    \begin{macrocode}
\cs_new:Npn\timechartmakebeforeyear #1
  {
    #1\nobreakspace\textsc{bce}
  }
\cs_new:Npn\timechartmakeafteryear #1
  {
    #1\nobreakspace\textsc{ce}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Bounding box}
%
% \begin{macro}{\@@_nogrid_bounding_box_set:}
% Set the bounding box when no grid is being drawn.
%    \begin{macrocode}
\cs_new:Npn\@@_nogrid_bounding_box_set:
  {
    \pgfpathmoveto
      { \pgfpoint{\l_@@_start_x}{\l_@@_content_bottom_y} }
    \pgfpathmoveto
      { \pgfpoint{\l_@@_finish_x}{\l_@@_content_top_y} }
    \pgfusepath{discard}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Positioning}
%
% \begin{macro}{\@@_set_y_user:m}
%   Set current \(y\) coordinate to \param{1}. This macro will be made available as \cs{timechartsety} in the
%   \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_set_y_user:m #1
  {
    \pgfmathsetmacro{\l_@@_current_y}{#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_save_y_user:}
%   Save the current \(y\) coordinate. This macro will be made available as \cs{timechartsavey} in the
%   \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_save_y_user:
  {
    \pgfmathsetmacro{\l_@@_saved_y}{\l_@@_current_y}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_reset_y_user:}
%   Set the current \(y\) coordinate to the last saved coordinate. This macro will be made available as
%   \cs{timechartsresety} in the \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_reset_y_user:
  {
    \pgfmathsetmacro{\l_@@_current_y}{\l_@@_saved_y}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_set_y_minimum_auto_reset_user:m}
%   Set a \(y\) coordinate below which \cs{@@_step_y_user:} will automatically reset the currrent \(y\) coordinate to
%   the last saved \(y\) coordinate. This macro will be made available as \cs{timechartssetyminimumautoreset} in the
%   \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_set_y_minimum_auto_reset_user:m #1
  {
    \pgfmathsetmacro{\l_@@_auto_reset_minimum_y}{#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_set_y_maximum_auto_reset_user:m}
%   Set a \(y\) coordinate above which \cs{@@_step_y_user:} will automatically reset the currrent \(y\) coordinate to
%   the last saved \(y\) coordinate. This macro will be made available as \cs{timechartssetymaximumautoreset} in the
%   \env{timechart} environment.
%    \begin{macrocode}
\cs_new:Npn\@@_set_y_maximum_auto_reset_user:m #1
  {
    \pgfmathsetmacro{\l_@@_auto_reset_maximum_y}{#1}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_step_y_user:O}
%   Increment the current \(y\) coordinate by \param{1} times the length specified in \key{/timechart/ystep}. This
%   macro will be made available as \cs{timechartstepy} in the \env{timechart} environment.
%    \begin{macrocode}
\NewDocumentCommand{\@@_step_y_user:O}{ O{1} }
  {
    \pgfmathsetmacro{\l_@@_current_y}
      {\l_@@_current_y+#1*\l_@@_ystep_pgf}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      {
        or(
          \l_@@_current_y<\l_@@_auto_reset_minimum_y,
          \l_@@_current_y>\l_@@_auto_reset_maximum_y
        )
      }
    \bool_if:nT{\l_@@_tmpa_bool}
      { \pgfmathsetmacro{\l_@@_current_y}{\l_@@_saved_y)} }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Bounds checking}
%
% \begin{macro}{\@@_if_x_in_bounds:nT}%
%   Check if \(x\) coordinate \param{1} is (strictly) within the bounds of the chart; if so, execute \param{2}.
%    \begin{macrocode}
\cs_new:Npn\@@_if_x_in_bounds:nT #1#2
  {
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}{
      and(
        #1>=\l_@@_start_x,
        #1<=\l_@@_finish_x
      )
    }
    \bool_if:NT\l_@@_tmpa_bool
      {#2}
  }

%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_if_x_range_intersect_bounds_x:nnT}%
%   Check if the range between \(x\) coordinates \param{1} and \param{2} intersects the range of the bounds of the
%   chart; if so, execute \param{3}.
%    \begin{macrocode}
\cs_new:Npn\@@_if_x_range_intersect_bounds:nnT #1#2#3
  {
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}{
      or(
        or(
          and(
            #2>=\l_@@_start_x,
            #2<=\l_@@_finish_x
          ),
          and(
            #1>=\l_@@_start_x,
            #1<=\l_@@_finish_x
          )
        ),
        and(
          #1<\l_@@_start_x,
          #2>\l_@@_finish_x
        )
      )
    }
    \bool_if:NT\l_@@_tmpa_bool
      {#3}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Date and date range parsing}
%
% \begin{macro}{\@@_parse_date_or_daterange:NNNNNn}
%   Parse the text in \param{6}, which should represent a date or date range, into parameters \param{1}--\param{5}.
%   \begin{arguments}
%     \item range indicator boolean variable.
%     \item minimum circa indicator boolean variable.
%     \item minimum variable.
%     \item maximum circa indicator boolean variable.
%     \item maximum variable.
%     \item text to parse.
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn\@@_parse_date_or_daterange:NNNNNn #1#2#3#4#5#6
{
  \bool_set:Nn #1 {\@@_is_nondaterange_p:w #6/\q_stop}
  \bool_set_inverse:N #1
  \bool_if:nTF #1
    { \@@_parse_range:w #2#3#4#5\q_mark #6\q_stop }
    {
      \@@_parse_date:NNn #2#3{#6}
      \bool_set_eq:NN #4#2
      \pgfmathsetmacro{#5}{#3}
    }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_is_nondaterange_p:w}
%   To be called in the form \cs{@@_is_nondaterange_p:w}\meta{text}\texttt{/}\cs{q_stop}. Return boolean true if and
%   only if \meta{text} (known to be either a date or date range) contains a range marker.
%    \begin{macrocode}
\cs_new:Npn\@@_is_nondaterange_p:w #1/#2\q_stop
{
  \tl_if_empty_p:n{#2}
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_parse_range:w}
%   To be called in the form
%   \cs{@@_parse_range:w}\meta{cmin}\meta{min}\meta{cmax}\meta{max}\cs{q_mark}\meta{text}\cs{q_stop}. Parse \meta{text}
%   (known to represent a date range) into minimum circa indicator boolean variable \meta{cmin}, minimum variable
%   \meta{min}, maximum circa indicator boolean variable \meta{cmax}, maximum variable \meta{max}.
%    \begin{macrocode}
\cs_new:Npn\@@_parse_range:w #1#2#3#4\q_mark #5/#6\q_stop
{
  \_@@_parse_date:NNn #1#2{#5}
  \_@@_parse_date:NNn #3#4{#6}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_parse_date:NNn}
%   Parse text (known to represent a date) into the supplied variables. Parameters \param{1} and \param{2} are the
%   variables for (respectively) circa indicator boolean and date, and \param{3} is the text to be parsed:
%   \begin{arguments}
%     \item circa indicator boolean variable.
%     \item date variable.
%     \item text to parse.
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn\@@_parse_date:NNn #1#2#3
{
  \bool_set:Nn #1 { \@@_is_circa_p:w #3c\q_stop }
  \bool_if:NTF #1
    { \@@_parse_circa_date:w #2\q_mark #3\q_stop }
    { \@@_parse_noncirca_date:Nn #2{#3} }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_is_circa_p:w}
%   To be called in the form \cs{@@_is_circa_p:w}\meta{text}\texttt{c}\cs{q_stop}. Return boolean true if and only if
%   \meta{text} (known to be either a date or a date with a circa indicator) has a circa indicator.
%    \begin{macrocode}
\cs_new:Npn\@@_is_circa_p:w #1c#2\q_stop
{
  \tl_if_empty_p:n{#1}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_parse_circa_date:w}
%   To be called in the form \cs{@@_parse_circa_date:w}\meta{var}\cs{q_mark}\meta{text}\cs{q_stop}. Parse \meta{text}
%   (known to represent a circa date) into the supplied variable. \param{1} is the variable for the date and \param{2}
%   is the text to be parsed.
%    \begin{macrocode}
\cs_new:Npn\@@_parse_circa_date:w #1\q_mark c#2\q_stop
{
  \@@_parse_noncirca_date:Nn #1{#2}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_parse_noncirca_date:w}
%   To be called in the form \cs{@@_parse_noncirca_date:w}\meta{var}\cs{q_mark}\meta{text}\break\cs{q_stop}. Parse
%   \meta{text} (known to represent a non-circa date) into the supplied variable. \param{1} is the variable for the date
%   and \param{2} is the text to be parsed.
%    \begin{macrocode}
\cs_new:Npn\@@_parse_noncirca_date:Nn #1#2
{
  \bool_if:nTF { \@@_is_before_p:w #2-\q_stop }
    { \@@_parse_before_date:w #1\q_mark #2\q_stop }
    { \@@_parse_signed_date:w #1\q_mark #2-0-0\q_stop }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_is_before_p:w}
%   To be called in the form \cs{@@_is_before_p:w}\meta{text}\texttt{-}\cs{q_stop}. Return boolean true if and only if
%   \meta{text} (known to be a date without a circa indicator) begins with a \texttt{-}.
%    \begin{macrocode}
\cs_new:Npn\@@_is_before_p:w #1-#2\q_stop
{
  \tl_if_empty_p:n{#1}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_parse_before_date:w}
%   To be called in the form \cs{@@_parse_before_date:w}\meta{var}\cs{q_mark}\meta{text}\cs{q_stop}. Parse \meta{text}
%   (known to represent a date with a leading \texttt{-}) into the supplied variable. \param{1} is the variable for the
%   date and \param{2} is the text to be parsed.
%    \begin{macrocode}
\cs_new:Npn\@@_parse_before_date:w #1\q_mark-#2\q_stop
{
  \@@_parse_signed_date:w #1-\q_mark #2-0-0\q_stop
}
%    \end{macrocode}
% \end{macro}
%
% Now comes that actual parsing of an ISO-format date \texttt{YYYY-MM-DD}. The following macros serve as lookup tables
% for the number of days in the \(n\)-th month and the number of days in the year up to the start of the \(n\)-th month.
%    \begin{macrocode}
\cs_new:cpn{c_@@_year_days_pgf}{365}
\cs_new:cpn{c_@@_month_days_1_pgf}{31}
\cs_new:cpn{c_@@_month_days_2_pgf}{28}
\cs_new:cpn{c_@@_month_days_3_pgf}{31}
\cs_new:cpn{c_@@_month_days_4_pgf}{30}
\cs_new:cpn{c_@@_month_days_5_pgf}{31}
\cs_new:cpn{c_@@_month_days_6_pgf}{30}
\cs_new:cpn{c_@@_month_days_7_pgf}{31}
\cs_new:cpn{c_@@_month_days_8_pgf}{31}
\cs_new:cpn{c_@@_month_days_9_pgf}{30}
\cs_new:cpn{c_@@_month_days_10_pgf}{31}
\cs_new:cpn{c_@@_month_days_11_pgf}{30}
\cs_new:cpn{c_@@_month_days_12_pgf}{31}
\cs_new:cpn{c_@@_cumulative_days_1_pgf}{0}
\cs_new:cpn{c_@@_cumulative_days_2_pgf}{31}
\cs_new:cpn{c_@@_cumulative_days_3_pgf}{59}
\cs_new:cpn{c_@@_cumulative_days_4_pgf}{90}
\cs_new:cpn{c_@@_cumulative_days_5_pgf}{120}
\cs_new:cpn{c_@@_cumulative_days_6_pgf}{151}
\cs_new:cpn{c_@@_cumulative_days_7_pgf}{181}
\cs_new:cpn{c_@@_cumulative_days_8_pgf}{212}
\cs_new:cpn{c_@@_cumulative_days_9_pgf}{243}
\cs_new:cpn{c_@@_cumulative_days_10_pgf}{273}
\cs_new:cpn{c_@@_cumulative_days_11_pgf}{304}
\cs_new:cpn{c_@@_cumulative_days_12_pgf}{334}
%    \end{macrocode}
%
% \begin{macro}{\@@_parse_signed_date:w}
%   To be called in the form \cs{@@_parse_positive_date:w}\meta{var}\meta{sign}\cs{q_mark}\break
%   \meta{text}\texttt{-0-0}\cs{q_stop}. Parse \meta{text} (known to represent a non-circa date) into the supplied
%   variable. \param{1} is the variable for the date and \param{2} is possibly \texttt{-}.
%
%   There is a trick in the parsing:
%   \begin{enumerate}
%       \item If \meta{text} has the form \meta{year}\texttt{-}\meta{month}\texttt{-}\meta{day}, then parameters
%             \param{3}, \param{4}, and \param{5} will be, respectively, \meta{year}, \meta{month}, and
%             \meta{day}\texttt{-0-0}. Thus \param{5} will be evaulated by \pkg{pgfmath} to \meta{day}.
%       \item If \meta{text} has the form \meta{year}\texttt{-}\meta{month}, then parameters \param{3}, \param{4}, and
%             \param{5} will be, respectively, \meta{year}, \meta{month}, and \texttt{0-0}. Thus \param{5} will be
%             evaulated by \pkg{pgfmath} to \(0\).
%       \item If \meta{text} is simply \meta{year}, then parameters \param{3}, \param{4}, and \param{5} will be,
%             respectively, \meta{year}, \texttt{0}, and \texttt{0}.
%     \end{enumerate}
%    \begin{macrocode}
\cs_new:Npn\@@_parse_signed_date:w #1#2\q_mark #3-#4-#5\q_stop
{
  \pgfmathtruncatemacro{\@@_parsed_year_pgf}{#2#3}
  \pgfmathtruncatemacro{\@@_parsed_month_pgf}{#4}
  \pgfmathtruncatemacro{\@@_parsed_day_pgf}{#5}
  \@@_pgfmathsetbool:nn{\l_tmpa_bool}{
    or(
      \@@_parsed_month_pgf < 1,
      \@@_parsed_month_pgf > 12,
    )
  }
  \bool_if:NTF\l_tmpa_bool
  {
%    \end{macrocode}
%   \textit{Case: no valid month is given.} Use only the year.
%    \begin{macrocode}
    \pgfmathsetmacro{#1}{#2#3}
  }
  {
%    \end{macrocode}
%   \textit{Case: a valid month is given.} Get the number of days in the year, in the month, and in the year up to the
%   month. Then check if the year is a leap year and, if so, make the appropriate adjustments.
%    \begin{macrocode}
    \cs_set_eq:NN\l_@@_year_days_pgf\c_@@_year_days_pgf
    \cs_set_eq:Nc\l_@@_month_days_pgf
      { c_@@_month_days_\@@_parsed_month_pgf _pgf }
    \cs_set_eq:Nc\l_@@_cumulative_days_pgf
      { c_@@_cumulative_days_\@@_parsed_month_pgf _pgf }
    \@@_pgfmathsetbool:nn{\l_tmpa_bool}{
      or(
        Mod(\@@_parsed_year_pgf,400) == 0,
        and(
          Mod(\@@_parsed_year_pgf,4) == 0,
          Mod(\@@_parsed_year_pgf,100) != 0
        )
      )
    }
    \bool_if:NT\l_tmpa_bool
      {
        \pgfmathsetmacro{\l_@@_year_days_pgf}
          { \l_@@_year_days_pgf+1 }
        \@@_pgfmathsetbool:nn{\l_tmpb_bool}
          { \@@_parsed_month == 1 }
        \bool_if:NF\l_tmpb_bool
          {
            \@@_pgfmathsetbool:nn{\l_tmpb_bool}
              { \@@_parsed_month == 2 }
            \bool_if:NF\l_tmpb_bool
              {
                \pgfmathsetmacro{\l_@@_month_days_pgf}
                  { \l_@@_month_days_pgf + 1 }
              }
              {
                \pgfmathsetmacro{\l_@@_cumulative_days_pgf}
                  { \l_@@_cumulative_days_pgf + 1 }
              }
          }
      }
    \@@_pgfmathsetbool:nn{\l_tmpa_bool}{
      or(
        \@@_parsed_day_pgf < 1,
        \@@_parsed_day_pgf > \l_@@_month_days_pgf,
      )
    }
    \bool_if:NTF\l_tmpa_bool
      {
%    \end{macrocode}
%   \textit{Sub-case: no valid day is given.} Use only the year and month.
%    \begin{macrocode}
       \pgfmathsetmacro{#1}
         {
           #2#3
           + \l_@@_cumulative_days_pgf/\l_@@_year_days_pgf
         }
      }
      {
%    \end{macrocode}
%   \textit{Sub-case: a valid day is given.} Use the year, month, and day.
%    \begin{macrocode}
       \pgfmathsetmacro{#1}
         {
           #2#3
           + (
               \l_@@_cumulative_days_pgf
               + \@@_parsed_day_pgf
             )/\l_@@_year_days_pgf
         }
      }
  }
}
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Interval drawing}
%
% \subsubsection{Preliminaries}
%
% \begin{macro}{
%   \l_@@_start_is_range_bool,
%   \l_@@_interval_start_min_circa_bool,
%   \l_@@_interval_start_max_circa_bool,
%   \l_@@_finish_is_range_bool,
%   \l_@@_interval_finish_min_circa_bool,
%   \l_@@_interval_finish_max_circa_bool,
% }
%   These boolean variables will be used to hold parsed data for the start and finish of an interval: whether it is a
%   range, whether the beginning of that range is qualified by `circa', and whether the end of that range is qualified
%   by `circa'.
%    \begin{macrocode}
\bool_new:N\l_@@_start_is_range_bool
\bool_new:N\l_@@_interval_start_min_circa_bool
\bool_new:N\l_@@_interval_start_max_circa_bool
\bool_new:N\l_@@_finish_is_range_bool
\bool_new:N\l_@@_interval_finish_min_circa_bool
\bool_new:N\l_@@_interval_finish_max_circa_bool
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Error message definition}
%
%    \begin{macrocode}
\msg_new:nnn{timechart}{interval_dates_invalid}
  { Invalid~interval~dates:~#1~to~#2 }
%    \end{macrocode}
%
%
%
% \subsubsection{Main macros}
%
% \begin{macro}{\@@_interval_user:Ommm}
%   Draw an interval. This macro will be made available as \cs{timechartinterval} inside the \env{timechart}
%   environment. It is simply a wrapper around the internal \cs{@@_interval:nnnn} macro.
%   \begin{arguments}
%     \item PGF keys under \key{/timechart/} to apply.
%     \item Start year.
%     \item Finish year.
%     \item Label.
%   \end{arguments}
%    \begin{macrocode}
\NewDocumentCommand{\@@_interval_user:Ommm}{ O{} m m m }
  {
    \@@_interval:nnnn{#1}{#2}{#3}{#4}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval:nnnn}
%   Internal macro for drawing an interval.
%    \begin{macrocode}
\cs_new:Npn \@@_interval:nnnn #1#2#3#4
  {
    \@@_debug:n{
      ************************************************************
    }
    \@@_debug:n{Interval~#2~to~#3~"#4"}
%    \end{macrocode}
%   Open an group and parse the start and finish dates or date ranges.
%    \begin{macrocode}
    \group_begin:
    \@@_parse_date_or_daterange:NNNNNn
      \l_@@_start_is_range_bool
      \l_@@_interval_start_min_circa_bool
      \l_@@_interval_start_min_year
      \l_@@_interval_start_max_circa_bool
      \l_@@_interval_start_max_year
      {#2}
    \@@_parse_date_or_daterange:NNNNNn
      \l_@@_finish_is_range_bool
      \l_@@_interval_finish_min_circa_bool
      \l_@@_interval_finish_min_year
      \l_@@_interval_finish_max_circa_bool
      \l_@@_interval_finish_max_year
      {#3}
%    \end{macrocode}
%   Check the results of parsing.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_tmpa_bool}{
      and(
        \l_@@_interval_start_min_year
          <= \l_@@_interval_start_max_year,
        and(
          \l_@@_interval_start_max_year
            <= \l_@@_interval_finish_min_year,
          \l_@@_interval_finish_min_year
            <= \l_@@_interval_finish_max_year
        )
      )
    }
%    \end{macrocode}
%   Proceed if and only if the results of parsing are valid, otherwise output an error message. In both cases, close the
%   group and, in the former case, step the \(y\) coordinate if appropriate.
%    \begin{macrocode}
    \bool_if:NTF\l_tmpa_bool
      {
        \@@_interval_checked:nn{#1}{#4}
        \group_end:
        \bool_if:NT\l_@@_autostep_bool
          { \@@_step_y_user:O }
      }
      {
        \msg_error:nnnn{timechart}{interval_dates_invalid}{#2}{#3}
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% In \cs{@@_interval_user_aux:nnnn}, the start and finish dates were parsed and it has been checked that they satisfy
% \begin{align*}
%   &\cs{l_@@_interval_start_min_year} \\
%   &\qquad\leq \cs{l_@@_interval_start_max_year} \\
%   &\qquad\qquad\leq \cs{l_@@_interval_finish_min_year} \\
%   &\qquad\qquad\qquad\leq \cs{l_@@_interval_finish_max_year}.
% \end{align*}
% In the code that follows, horizontal coordinates \cs[no-index]{l_@@_interval_..._x} will be computed from
% \cs[no-index]{l_@@_interval_..._year}. Subsequently, only the former variables will be used.
%
%
%
%
% \begin{macro}{\@@_interval_checked:nn}
%   Draw an interval using the parsed and checked start and finish dates
%   \begin{arguments}
%     \item PGF keys under \key{/timechart/} to apply.
%     \item Label.
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn \@@_interval_checked:nn #1#2
  {
%    \end{macrocode}
%   Process keys supplied locally and retrieve the only value needed at this stage.
%    \begin{macrocode}
    \pgfqkeys{/timechart}{
      #1,
      circa~uncertainty/.get=\l_@@_circa_uncertainty_year
    }
%    \end{macrocode}
%   Do the minimum amount of calculation necessary to check whether any part of interval is visible. This means
%   calculating \cs{l_@@_interval_start_min_x} and \cs{l_@@_interval_finish_max_x} (including taking into account any
%   `circa').
%    \begin{macrocode}
    \bool_if:NTF\l_@@_interval_start_min_circa_bool
      {
        \pgfmathsetmacro{\l_@@_interval_start_min_x}
          { yeartox(\l_@@_interval_start_min_year
            - \l_@@_circa_uncertainty_year) }
      }
      {
        \pgfmathsetmacro{\l_@@_interval_start_min_x}
          { yeartox(\l_@@_interval_start_min_year) }
      }
    \bool_if:NTF\l_@@_interval_finish_max_circa_bool
      {
        \pgfmathsetmacro{\l_@@_interval_finish_max_x}
          { yeartox(\l_@@_interval_finish_max_year
            + \l_@@_circa_uncertainty_year) }
      }
      {
        \pgfmathsetmacro{\l_@@_interval_finish_max_x}
          { yeartox(\l_@@_interval_finish_max_year) }
      }
%    \end{macrocode}
%   Proceed if some part of the interval is visible.
%    \begin{macrocode}
    \@@_if_x_range_intersect_bounds:nnT
      {\l_@@_interval_start_min_x}
      {\l_@@_interval_finish_max_x}
      { \@@_draw_visible_interval:nn{#1}{#2} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_start_beyond_bool,\@@_finish_beyond_bool}
%   Boolean variables to indicate whether the interval extends beyond the chart at the start or the finish more than the
%   specified tolerance.
%    \begin{macrocode}
\bool_new:N\l_@@_interval_start_beyond_bool
\bool_new:N\l_@@_interval_finish_beyond_bool
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{@@_draw_visible_interval:nn}
%   Draw an interval of which some part is known to be visible.
%   \begin{arguments}
% \item PGF keys
% \item Label
%   \end{arguments}
%    \begin{macrocode}
\cs_new:Npn\@@_draw_visible_interval:nn #1#2
  {
%    \end{macrocode}
%   Retrieve PGF key values.
%    \begin{macrocode}
    \pgfqkeys{/timechart}{
      tolerance~start/.get=\l_@@_start_tolerance_pgf,
      tolerance~finish/.get=\l_@@_finish_tolerance_pgf,
      beyond~length~start/.get=\l_@@_start_beyond_length_pgf,
      beyond~length~finish/.get=\l_@@_finish_beyond_length_pgf,
      beyond~x~radius~start/.get=\l_@@_start_beyond_x_radius_pgf,
      beyond~x~radius~finish/.get=\l_@@_finish_beyond_x_radius_pgf,
      ref/.get=\l_@@_ref_text,
      mark/.get=\l_@@_mark_text,
      interval~minimum~width/.get=\l_@@_minimum_width_pgf,
      interval~bar~color/.get=\l_@@_bar_color,
      interval~bar~thickness/.get=\l_@@_bar_thickness_pgf,
      interval~mark~color/.get=\l_@@_mark_color,
      interval~label~baseline/.get=\l_@@_text_baseline_pgf,
      interval~label~node~name/.get=\l_@@_interval_label_node_name,
    }
%    \end{macrocode}
% Calculate the start and finish tolerance and beyond indicator \(x\) coordinates.
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_start_tolerance_x}{
      \l_@@_start_x-(\l_@@_start_tolerance_pgf)
    }
    \pgfmathsetmacro{\l_@@_finish_tolerance_x}{
      \l_@@_finish_x+(\l_@@_finish_tolerance_pgf)
    }
    \pgfmathsetmacro{\l_@@_start_beyond_x}{
      \l_@@_start_x-(\l_@@_start_beyond_length_pgf)
    }
    \pgfmathsetmacro{\l_@@_finish_beyond_x}{
      \l_@@_finish_x+(\l_@@_finish_beyond_length_pgf)
    }
%    \end{macrocode}
%   Do the remaining calculations: calculate \cs{l_@@_interval_start_max_x} and \cs{l_@@_interval_finish_min_x}
%   (including taking into account any `circa').
%    \begin{macrocode}
    \pgfmathsetlengthmacro{\l_@@_bar_half_thickness_pgf}
      {.5*\l_@@_bar_thickness_pgf}
    \cs_set:Npn\l_@@_label_text{#2}
    \bool_if:NTF\l_@@_interval_start_max_circa_bool
      {
        \pgfmathsetmacro{\l_@@_interval_start_max_x}
          { yeartox(\l_@@_interval_start_max_year
            + \l_@@_circa_uncertainty_year) }
      }
      {
        \pgfmathsetmacro{\l_@@_interval_start_max_x}
          { yeartox(\l_@@_interval_start_max_year) }
      }
    \bool_if:NTF\l_@@_interval_finish_min_circa_bool
      {
        \pgfmathsetmacro{\l_@@_interval_finish_min_x}
          { yeartox(\l_@@_interval_finish_min_year
            - \l_@@_circa_uncertainty_year) }
      }
      {
        \pgfmathsetmacro{\l_@@_interval_finish_min_x}
          { yeartox(\l_@@_interval_finish_min_year) }
      }
%    \end{macrocode}
%   It is possible that circa indicators have made \cs{l_@@_start_max_x} greater than \cs{l_@@_finish_min_x}.
%   Check for this; if so, set them both to their average.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      {
        \l_@@_interval_start_max_x
          > \l_@@_interval_finish_min_x
      }
    \bool_if:NT\l_@@_tmpa_bool
      {
        \pgfmathsetmacro{\l_@@_interval_start_max_x}
          {
            .5*(
              \l_@@_interval_start_max_x
              + \l_@@_interval_finish_min_x
            )
          }
        \pgfmathsetmacro{\l_@@_interval_finish_min_x}
          { \l_@@_interval_start_max_x }
      }
%    \end{macrocode}
%   Check whether the minimum width requirement is satisfied; if not, make an adjustment.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      {
        (\l_@@_interval_finish_max_x
          -\l_@@_interval_start_min_x)
        > \l_@@_minimum_width_pgf
      }
    \bool_if:NF \l_@@_tmpa_bool
    {
      \pgfmathsetmacro{\l_@@_width_adjust}
        { .5*\l_@@_minimum_width_pgf }
      \pgfmathsetmacro{\l_@@_interval_start_max_x}
        { \l_@@_interval_start_max_x-\l_@@_width_adjust }
      \pgfmathsetmacro{\l_@@_interval_finish_min_x}
        { \l_@@_interval_finish_min_x+\l_@@_width_adjust }
      \pgfmathsetmacro{\l_@@_interval_start_min_x}
        {
          min(
            \l_@@_interval_start_min_x,
            \l_@@_interval_start_max_x
          )
        }
      \pgfmathsetmacro{\l_@@_interval_finish_max_x}
        {
          max(
            \l_@@_interval_finish_max_x,
            \l_@@_interval_finish_min_x
          )
        }
    }
    \@@_debug:n{Calculated+adjusted~x~coords:}
    \@@_debug:n{~
      \l_@@_interval_start_min_x/\l_@@_interval_start_max_x~
      to~
      \l_@@_interval_finish_min_x/\l_@@_interval_finish_max_x
    }
%    \end{macrocode}
%   At this point, the \(x\)-coordinates of the interval have been established. First, decide whether the interval
%   exceeds the chart by more than the tolerance at the start and the finish. If so, set the appropriate clipping path
%   (this may be changed again later).
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_interval_start_beyond_bool}
      {\l_@@_interval_start_min_x<=\l_@@_start_tolerance_x}
    \bool_if:NT\l_@@_interval_start_beyond_bool
      {
        \cs_set_eq:NN
          \@@_interval_start_clip_path:
          \@@_interval_start_clip_path_beyond:
      }
    \@@_pgfmathsetbool:nn{\l_@@_interval_finish_beyond_bool}
      {\l_@@_interval_finish_max_x>=\l_@@_finish_tolerance_x}
    \bool_if:NT\l_@@_interval_finish_beyond_bool
      {
        \cs_set_eq:NN
          \@@_interval_finish_clip_path:
          \@@_interval_finish_clip_path_beyond:
      }
%    \end{macrocode}
%   Compute how the interval will be drawn. There are three components:
%   \begin{itemize}
%     \item the \emph{startrange}, comprising the part between \cs{l_@@_interval_start_min_x} to
%             \cs{l_@@_interval_start_max_x};
%     \item the definite part:  \cs{l_@@_interval_start_max_x} to \cs{l_@@_interval_finish_min_x};
%     \item the \emph{finishrange}: \cs{l_@@_interval_finish_min_x} to \cs{l_@@_interval_finish_max_x}.
%   \end{itemize}
%   It is necessary to decide which of these will be drawn. The logic is complicated because any part may lie outside
%   the timechart or be involved in the beyond indicator. Further, clipping is used for a `slant' startrange or
%   finishrange and for beyond indicators.
%
%   First of all, consider the definite part. Depending on where this is located, it may be unnecessary to compute or
%   draw the startrange or finishrange, so some of the following macros may be set to do nothing.
%    \begin{macrocode}
    \@@_interval_definite_compute:
    \@@_interval_startrange_compute:
    \@@_interval_finishrange_compute:
%    \end{macrocode}
%   All the data needed to draw the interval are now ready. Shift to the correct vertical coordinate and open a scope for
%   drawing.
%    \begin{macrocode}
    \pgftransformshift{ \pgfpoint{0}{\l_@@_current_y} }
    \pgfscope
%    \end{macrocode}
%   First, do the computed clipping, for a slant startrange and/or a slant finishrange, or beyond indicators. Then draw
%   the startrange, finish range, and then the `solid' part, which may be only the definite part or may include a slant
%   startrange or a slant finishrange. Finally, define the node for the bar, then do the labelling.
%    \begin{macrocode}
    \@@_interval_clip:
    \@@_interval_startrange_draw:
    \@@_interval_finishrange_draw:
    \@@_interval_solid_draw:
    \@@_interval_mark:
    \@@_interval_define_bar_node:
    \endpgfscope
    \@@_interval_label:
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Computation}
%
% These macros determine precisely what is to be drawn. The aim is to minimize the number of drawing commands by
% avoiding drawing where areas that would be clipped.
%
%
%
% \paragraph{Definite part of the interval}
%
% \begin{macro}{\@@_interval_definite_compute:}
%   Compute whether and where to draw the definite part of the interval. Two auxiliary macros,
%   \cs{@@_interval_definite_compute_ii:} and \cs{@@_interval_definite_compute_ii:} are used, simply to avoid deep
%   nesting of code.
%
%   First, check whether the entire definite part of the interval is located to the left of the start of the chart and
%   that the interval does exceed the start tolerance. In this case, the only thing that might be drawn to appear to the
%   left of the start will be the excess indicator drawn as part of the finish range, so there is no need to draw the
%   definite part or do anything for the start range.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_definite_compute:
  {
    \@@_debug:n{Computing:~definite~part}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      { \l_@@_interval_finish_min_x < \l_@@_start_x }
    \bool_if:nTF{
      \l_@@_tmpa_bool && \l_@@_interval_start_beyond_bool
    }
      {
        \cs_set_eq:NN
          \@@_interval_solid_draw:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_startrange_compute:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_startrange_draw:\prg_do_nothing:
      }
      {
        \@@_interval_definite_compute_ii:
      }
  }
%    \end{macrocode}
%   Second, check whether the entire definite part of the interval is located to the right of the finish of the chart
%   and that the interval does exceed the finish tolerance. In this case, the only thing that might be drawn to appear
%   to the right of the finish will be the excess indicator drawn as part of the start range, so there is no need to
%   draw the definite part or do anything for the finish range.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_definite_compute_ii:
  {
    \@@_debug:n{~(Stage~II)}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      { \l_@@_interval_start_max_x > \l_@@_finish_x }
    \bool_if:nTF{
      \l_@@_tmpa_bool && \l_@@_interval_finish_beyond_bool
    }
      {
        \cs_set_eq:NN
          \@@_interval_solid_draw:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_finishrange_compute:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_finishrange_draw:\prg_do_nothing:
      }
      {
        \@@_interval_definite_compute_iii:
      }
  }
%    \end{macrocode}
%   At this point, some part of the definite part of the interval has to be drawn.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_definite_compute_iii:
  {
    \@@_debug:n{~(Stage~III)}
%    \end{macrocode}
%   If the start of the definite part of the interval is at or to the left of the start of the chart and the interval
%   exceeds the start tolerance, set the start of the solid part to the position of the start excess indicator. In this
%   case, nothing needs to be done for the start range. Otherwise, set the start of the solid part to the start of the
%   definite part.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      { \l_@@_interval_start_max_x <= \l_@@_start_x }
    \bool_if:nTF{
      \l_@@_tmpa_bool && \l_@@_interval_start_beyond_bool
    }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_start_x\l_@@_start_beyond_x
        \cs_set_eq:NN
          \@@_interval_startrange_compute:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_startrange_draw:\prg_do_nothing:
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_start_x
          \l_@@_interval_start_max_x
      }
%    \end{macrocode}
%   If the finish of the definite part of the interval is at or to the right of the finish of the chart and the interval
%   exceeds the finish tolerance, set the finsih of the solid part to the position of the finish excess indicator. In
%   this case, nothing needs to be done for the start range. Otherwise, set the start of the solid part to the start of
%   the definite part.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpb_bool}
      { \l_@@_interval_finish_min_x >= \l_@@_finish_x }
    \bool_if:nTF{
      \l_@@_tmpb_bool && \l_@@_interval_finish_beyond_bool
    }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_finish_x\l_@@_finish_beyond_x
        \cs_set_eq:NN
          \@@_interval_finishrange_compute:\prg_do_nothing:
        \cs_set_eq:NN
          \@@_interval_finishrange_draw:\prg_do_nothing:
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_finish_x
          \l_@@_interval_finish_min_x
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Startrange}
%
% \begin{macro}{\@@_interval_startrange_compute:}
%   Compute how to draw the startrange of an interval. This macro will only be called if it is necessary to draw some
%   part of the startrange.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_compute:
  {
    \@@_debug:n{Computing:~startrange}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      {
        \l_@@_interval_start_min_x
          == \l_@@_interval_start_max_x
      }
    \bool_if:NTF\l_@@_tmpa_bool
      {
        \cs_set_eq:NN\@@_interval_startrange_draw:\prg_do_nothing:
      }
      {
        \@@_interval_startrange_compute_ii:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_interval_startrange_compute_ii:}
%   Compute how to draw the startrange of an interval. This macro will only be called if the start range is non-empty.
%    \begin{macrocode}
\bool_new:N\l_@@_interval_startrange_finish_beyond_bool
\cs_new:Npn\@@_interval_startrange_compute_ii:
  {
    \@@_debug:n{~(Stage~II)}
%    \end{macrocode}
%   First, if the interval extends beyond the start tolerance then (since some part of the startrange) is visible, the
%   start excess indicator forms part of the range. In this case, the drawn range starts at the start of the timechart and the
%   start excess indicator mirrors this `level' of the range. Otherwise the drawn range starts at the extreme start of the
%   interval at `level' \(0\) and a start excess indicator is not drawn.
%    \begin{macrocode}
    \bool_if:NTF\l_@@_interval_start_beyond_bool
      {
        \cs_set_eq:NN
          \l_@@_interval_startrange_start_x\l_@@_start_x
        \pgfmathsetmacro{\l_@@_interval_startrange_start_level_pgf}
          {
            (\l_@@_interval_startrange_start_x
              -\l_@@_interval_start_min_x)
            /
            (\l_@@_interval_start_max_x
              -\l_@@_interval_start_min_x)
          }
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_startrange_start_x
          \l_@@_interval_start_min_x
        \pgfmathsetmacro
          {\l_@@_interval_startrange_start_level_pgf}{0}
      }
%    \end{macrocode}
%   Second, if the interval extends beyond the finish tolerance and the start of the definite part of the interval is to
%   the right of the finish of the timechart, the finish excess indicator forms part of the range. In this case, the
%   drawn range finishes at the finish of the timechart and the excess indicator mirrors this `level' of the range.
%   Otherwise the drawn range finishes at the extreme finish of the interval at `level' \(0\) and a finish excess
%   indicator is not drawn.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      { \l_@@_interval_start_max_x > \l_@@_finish_x }
    \bool_set:Nn\l_@@_interval_startrange_finish_beyond_bool
      {
        \l_@@_tmpa_bool
        && \l_@@_interval_finish_beyond_bool
      }
    \bool_if:NTF\l_@@_interval_startrange_finish_beyond_bool
      {
        \cs_set_eq:NN
          \l_@@_interval_startrange_finish_x
          \l_@@_finish_x
        \pgfmathsetmacro{\l_@@_interval_startrange_finish_level_pgf}
          {
            (\l_@@_interval_startrange_finish_x
              -\l_@@_interval_start_min_x)
            /
            (\l_@@_interval_start_max_x
              -\l_@@_interval_start_min_x)
          }
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_startrange_finish_x
          \l_@@_interval_start_max_x
        \pgfmathsetmacro
          {\l_@@_interval_startrange_finish_level_pgf}{1}
      }
    \int_case:nn {\l_@@_start_range_type_int}
      {
        {0}{
          \cs_set_eq:NN
            \@@_interval_startrange_draw:
            \@@_interval_startrange_draw_pseudofade:
        }
        {1}{
          \@@_interval_startrange_slant_compute:
        }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_startrange_slant_compute:}
%   Compute the clipping and drawing necessary for a slant startrange.
%    \begin{macrocode}
\cs_new:Npn \@@_interval_startrange_slant_compute:
  {
    \@@_debug:n{~(Startrange~slant)}
    \bool_if:NTF\l_@@_interval_start_beyond_bool
      {
        \bool_if:NTF\l_@@_interval_startrange_finish_beyond_bool
          {
            \cs_set_eq:NN
              \@@_interval_both_clip_path:
              \@@_interval_startrange_clip_path_beyond_both:
          }
          {
            \cs_set_eq:NN
              \@@_interval_start_clip_path:
              \@@_interval_startrange_clip_path_beyond_start:
          }
      }
      {
        \bool_if:NTF\l_@@_interval_startrange_finish_beyond_bool
          {
            \cs_set_eq:NN
              \@@_interval_both_clip_path:
              \@@_interval_startrange_clip_path_beyond_finish:
          }
          {
            \cs_set_eq:NN
              \@@_interval_start_clip_path:
              \@@_interval_startrange_clip_path_start:
          }
        }
    \cs_if_eq:NNTF\@@_interval_solid_draw:\prg_do_nothing:
      {
        \cs_set_eq:NN
          \@@_interval_startrange_draw:
          \@@_interval_startfinishrange_draw_slant:
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_start_x
          \l_@@_start_beyond_x
        \cs_set_eq:NN
          \@@_interval_startrange_draw:
          \prg_do_nothing:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Finishrange}
%
% \begin{macro}{\@@_interval_finishrange_compute:}
%   Compute how to draw the finishrange of an interval. This macro will only be called if it is necessary to draw some
%   part of the finishrange.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_compute:
  {
    \@@_debug:n{Computing:~finishrange}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      {
        \l_@@_interval_finish_max_x
          == \l_@@_interval_finish_min_x
      }
    \bool_if:NTF\l_@@_tmpa_bool
      {
        \cs_set_eq:NN\@@_interval_finishrange_draw:\prg_do_nothing:
      }
      {
        \@@_interval_finishrange_compute_ii:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_interval_finishrange_compute_ii:}
%   Compute how to draw the finishrange of an interval. This macro will only be called if the finishrange is non-empty.
%    \begin{macrocode}
\bool_new:N\l_@@_interval_finishrange_start_beyond_bool
\cs_new:Npn\@@_interval_finishrange_compute_ii:
  {
    \@@_debug:n{~(Stage~II)}
%    \end{macrocode}
%   First, if the interval extends beyond the finish tolerance then (since some part of the finishrange) is visible, the
%   finish excess indicator forms part of the range. In this case, the drawn range finishs at the finish of the
%   timechart and the finish excess indicator mirrors this `level' of the range. Otherwise the drawn range finishs at
%   the extreme finish of the interval at `level' \(0\) and a finish excess indicator is not drawn.
%    \begin{macrocode}
    \bool_if:NTF\l_@@_interval_finish_beyond_bool
      {
        \cs_set_eq:NN
          \l_@@_interval_finishrange_finish_x
          \l_@@_finish_x
        \pgfmathsetmacro{\l_@@_interval_finishrange_finish_level_pgf}
          {
            (\l_@@_interval_finishrange_finish_x
              -\l_@@_interval_finish_max_x)
            /
            (\l_@@_interval_finish_min_x
              -\l_@@_interval_finish_max_x)
          }
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_finishrange_finish_x
          \l_@@_interval_finish_max_x
        \pgfmathsetmacro
          {\l_@@_interval_finishrange_finish_level_pgf}{0}
      }

%    \end{macrocode}
%   Second, if the interval extends beyond the start tolerance and the finish of the definite part of the interval is to
%   the left of the start of the timechart, the start excess indicator forms part of the range. In this case, the
%   drawn range starts at the start of the timechart and the excess indicator mirrors this `level' of the range.
%   Otherwise the drawn range starts at the extreme start of the interval at `level' \(0\) and a start excess
%   indicator is not drawn.
%    \begin{macrocode}
    \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
      { \l_@@_interval_finish_min_x < \l_@@_start_x }
    \bool_set:Nn\l_@@_interval_finishrange_start_beyond_bool
      {
        \l_@@_tmpa_bool
        && \l_@@_interval_start_beyond_bool
      }
    \bool_if:NTF\l_@@_interval_finishrange_start_beyond_bool
      {
        \cs_set_eq:NN
          \l_@@_interval_finishrange_start_x
          \l_@@_start_x
        \pgfmathsetmacro{\l_@@_interval_finishrange_start_level_pgf}
          {
            (\l_@@_interval_finishrange_start_x
              -\l_@@_interval_finish_max_x)
            /
            (\l_@@_interval_finish_min_x
              -\l_@@_interval_finish_max_x)
          }
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_finishrange_start_x
          \l_@@_interval_finish_min_x
        \pgfmathsetmacro
          {\l_@@_interval_finishrange_start_level_pgf}{1}
      }
    \int_case:nn {\l_@@_finish_range_type_int}
      {
        {0}{
          \cs_set_eq:NN
            \@@_interval_finishrange_draw:
            \@@_interval_finishrange_draw_pseudofade:
        }
        {1}{
          \@@_interval_finishrange_slant_compute:
        }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_slant_compute:}
%   Compute the clipping and drawing necessary for a slant finishrange.
%    \begin{macrocode}
\cs_new:Npn \@@_interval_finishrange_slant_compute:
  {
    \@@_debug:n{~(Finishrange~slant)}
    \bool_if:NTF\l_@@_interval_finish_beyond_bool
      {
        \bool_if:NTF\l_@@_interval_finishrange_start_beyond_bool
          {
            \cs_set_eq:NN
              \@@_interval_both_clip_path:
              \@@_interval_finishrange_clip_path_beyond_both:
          }
          {
            \cs_set_eq:NN
              \@@_interval_finish_clip_path:
              \@@_interval_finishrange_clip_path_beyond_finish:
          }
      }
      {
        \bool_if:NTF\l_@@_interval_finishrange_start_beyond_bool
          {
            \cs_set_eq:NN
              \@@_interval_both_clip_path:
              \@@_interval_finishrange_clip_path_beyond_start:
          }
          {
            \cs_set_eq:NN
              \@@_interval_finish_clip_path:
              \@@_interval_finishrange_clip_path_finish:
          }
        }
    \cs_if_eq:NNTF\@@_interval_solid_draw:\prg_do_nothing:
      {
        \cs_set_eq:NN
          \@@_interval_finishrange_draw:
          \@@_interval_startfinishrange_draw_slant:
      }
      {
        \cs_set_eq:NN
          \l_@@_interval_solid_finish_x
          \l_@@_finish_beyond_x
        \cs_set_eq:NN
          \@@_interval_finishrange_draw:
          \prg_do_nothing:
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Drawing}
%
%
%
% \paragraph{Solid}
%
% \begin{macro}{\@@_interval_solid_draw:}
%   Draw the solid part of an interval.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_solid_draw:
  {
    \@@_debug:n{
      Drawing:~solid~\l_@@_interval_solid_start_x~
      to~\l_@@_interval_solid_finish_x
    }
    \pgfpathrectanglecorners{
      \pgfpoint
       {\l_@@_interval_solid_start_x}
       {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_interval_solid_finish_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfusepath{fill}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Start/finish range pseudofade}
%
% \begin{macro}{\@@_interval_startrange_draw_pseudofade:}
%   Draw a fading startrange and beyond indicators
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_draw_pseudofade:
  {
    \@@_debug:n{Drawing:~startrange,~pseudofade}
    \@@_debug:n{~
      \l_@@_interval_startrange_start_x~
      (\l_@@_interval_startrange_start_level_pgf)~
      to~\l_@@_interval_startrange_finish_x~
      (\l_@@_interval_startrange_finish_level_pgf)
    }
    \@@_interval_draw_pseudofade:nnnnn
      {\l_@@_interval_startrange_start_x}
      {\l_@@_interval_startrange_finish_x}
      {\l_@@_bar_color}
      {\l_@@_interval_startrange_start_level_pgf}
      {\l_@@_interval_startrange_finish_level_pgf}
    \bool_if:NT\l_@@_interval_start_beyond_bool
      { \@@_interval_startrange_start_beyond_draw_fade: }
    \bool_if:NT\l_@@_interval_startrange_finish_beyond_bool
      { \@@_interval_startrange_finish_beyond_draw_fade: }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_startrange_start_beyond_draw_fade:}
%   Draw a `faded' beyond indicator for a startrange that extends beyond the timechart start.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_start_beyond_draw_fade:
  {
    \@@_debug:n{Drawing:~startrange,~pseudofade~beyond~start}
    \@@_debug:n{~
      \l_@@_start_beyond_x~to~\l_@@_start_x
    }
    \pgfscope
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_start_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfsetfillopacity
      {\l_@@_interval_startrange_start_level_pgf}
    \pgfusepath{fill}
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_startrange_finish_beyond_draw_fade:}
%   Draw a `faded' beyond indicator for a startrange that extends beyond the timechart finish.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_finish_beyond_draw_fade:
  {
    \@@_debug:n{Drawing:~startrange,~pseudofade~beyond~finish}
    \@@_debug:n{~
      \l_@@_finish_beyond_x~to~\l_@@_finish_x
    }
    \pgfscope
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_finish_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfsetfillopacity
      {\l_@@_interval_startrange_finish_level_pgf}
    \pgfusepath{fill}
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\@@_interval_finishrange_draw_pseudofade:}
%   Draw a fading startrange and excess indicators
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_draw_pseudofade:
  {
    \@@_debug:n{Drawing:~finishrange,~pseudofade}
    \@@_debug:n{~
      \l_@@_interval_finishrange_start_x~
      (\l_@@_interval_finishrange_start_level_pgf)~
      to~\l_@@_interval_finishrange_finish_x~
      (\l_@@_interval_finishrange_finish_level_pgf)
    }
    \@@_interval_draw_pseudofade:nnnnn
      {\l_@@_interval_finishrange_start_x}
      {\l_@@_interval_finishrange_finish_x}
      {\l_@@_bar_color}
      {\l_@@_interval_finishrange_start_level_pgf}
      {\l_@@_interval_finishrange_finish_level_pgf}
    \bool_if:NT\l_@@_interval_finish_beyond_bool
      { \@@_interval_finishrange_finish_beyond_draw_fade: }
    \bool_if:NT\l_@@_interval_finishrange_start_beyond_bool
      { \@@_interval_finishrange_start_beyond_draw_fade: }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_finish_beyond_draw_fade:}
%   Draw a `faded' beyond indicator for a finishrange that extends beyond the timechart finish.
%    \begin{macrocode}

\cs_new:Npn\@@_interval_finishrange_finish_beyond_draw_fade:
  {
    \@@_debug:n{Drawing:~finishrange,~pseudofade~beyond~finish}
    \@@_debug:n{~
      \l_@@_finish_beyond_x~to~\l_@@_finish_x
    }
    \pgfscope
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_finish_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfsetfillopacity
      {\l_@@_interval_finishrange_finish_level_pgf}
    \pgfusepath{fill}
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_start_beyond_draw_fade:}
%   Draw a `faded' beyond indicator for a finishrange that extends beyond the timechart start.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_start_beyond_draw_fade:
  {
    \@@_debug:n{Drawing:~finishrange,~pseudofade~beyond~start}
    \@@_debug:n{~
      \l_@@_start_beyond_x~to~\l_@@_start_x
    }
    \pgfscope
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_start_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfsetfillopacity
      {\l_@@_interval_finishrange_start_level_pgf}
    \pgfusepath{fill}
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_draw_pseudofade:nnnnn}
%   Draw an imitation fading from \param{1} to \param {2} with color \param{3}, starting with opacity \param{4} and
%   ending with opacity \param{5}.
%    \begin{macrocode}
\pgfmathsetmacro{\l_@@_fadestep_pgf}{1}
\cs_new:Npn\@@_interval_draw_pseudofade:nnnnn #1#2#3#4#5
  {
    \@@_debug:n{Pseudofade:~#1~to~#2,~color~#3,~opacity~#4~to~#5}
    \group_begin:
    \pgfmathsetmacro{\start}{#1}
    \pgfmathsetmacro{\stop}{#2}
    \pgfmathsetmacro{\fadestep}
      {(\stop-\start)/(floor((\stop-\start)/\l_@@_fadestep_pgf)+1)}
    \pgfmathsetmacro{\startnext}{\start+\fadestep}
    \pgfmathsetmacro{\stopprev}{\stop-\fadestep}
    \pgfmathsetmacro{\denominator}{abs(\stop-\start)+\fadestep}
    \foreach \xa in {\start,\startnext,...,\stopprev} {
      \pgfmathsetlengthmacro{\o}
        {((\stop-\xa)*#4+(\xa-\start+\fadestep)*#5)/\denominator}
      \pgfscope
      \pgfpathrectanglecorners{
        \pgfpoint{\xa}{-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{\xa+\fadestep}{\l_@@_bar_half_thickness_pgf}
      }
      \pgfsetfillcolor{#3}
      \pgfsetfillopacity{\o}
      \pgfusepath{fill}
      \endpgfscope
    }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Start/finish range slant}
%
% \begin{macro}{\@@_interval_startfinishrange_draw_slant:}
%   Draw an already-clipped slanted start/finishrange and beyond indicators. This macro will only be called when there
%   is no `solid' part to drawn (for otherwise the solid part is extended to fill the start/finishrange), and so the
%   only thing to draw is the start/finishrange. Hence the macro can simply fill everything
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startfinishrange_draw_slant:
  {
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfsetfillcolor{\l_@@_bar_color}
    \pgfusepath{fill}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Clipping}
%
%
%
% \paragraph{Start/finish no-clipping paths}
%
% \begin{macro}{\c_@@_left_far_x,\c_@@_right_far_x}
%   No-clipping paths actually use the following \(x\)-coordinates, which are large in the positive and negative
%   direction.
%    \begin{macrocode}
\pgfmathsetmacro{\c_@@_left_far_x}{-16000pt}
\pgfmathsetmacro{\c_@@_right_far_x}{16000pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_start_clip_path_none:}
%   No clip path for start.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_start_clip_path_none:
  {
    \@@_debug:n{~Start~clip~path:~none}
    \pgfpathlineto{
      \pgfpoint
      {\c_@@_left_far_x}
      {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
      {\c_@@_left_far_x}
      {\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finish_clip_path_none:}
%   No clip path for finish.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finish_clip_path_none:
  {
    \@@_debug:n{~Finish~clip~path:~none}
    \pgfpathmoveto{
      \pgfpoint
      {\c_@@_right_far_x}
      {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
      {\c_@@_right_far_x}
      {-\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Start/finish beyond indicator clipping paths}
%
% \begin{macro}{\@@_interval_start_clip_path_beyond:}
%   Clip path for start beyond indicator.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_start_clip_path_beyond:
  {
    \@@_debug:n{~Start~clip~path:~beyond}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {-90}
      {90}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_bar_half_thickness_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finish_clip_path_beyond:}
%   Clip path for finish beyond indicator.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finish_clip_path_beyond:
  {
    \@@_debug:n{~Finish~clip~path:~beyond}
    \pgfpathmoveto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {90}
      {270}
      {\l_@@_finish_beyond_x_radius_pgf
        ~and~\l_@@_bar_half_thickness_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Startrange/finishrange clipping paths}
%
% \begin{macro}{\@@_interval_startrange_clip_path_start:}
%   Clip path for startrange.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_clip_path_start:
  {
    \@@_debug:n{~Start~clip~path:~startrange}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_startrange_start_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_startrange_start_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_startrange_finish_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_startrange_finish_x}
        {\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_clip_path_finish:}
%   Clip path for finishrange.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_clip_path_finish:
  {
    \@@_debug:n{~Finish~clip~path:~finishrange}
    \pgfpathmoveto{
      \pgfpoint
        {\l_@@_interval_finishrange_finish_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finishrange_finish_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finishrange_start_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finishrange_start_x}
        {-\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Startrange/finishrange clipping paths with `same side' beyond indicator}
%
% \begin{macro}{\@@_interval_startrange_clip_path_beyond_start:}
%   Clip path for startrange with start beyond indicator.
%    \begin{macrocode}
\cs_new:Npn \@@_interval_startrange_clip_path_beyond_start:
  {
    \@@_debug:n{~Start~clip~path:~startrange,~beyond~start}
    \pgfmathsetmacro{\l_@@_tmpa_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_startrange_start_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpb_pgf}{
      .5*\l_@@_tmpa_pgf
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {-90}
      {90}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_tmpb_pgf}
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpa_pgf}
      }
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_start_max_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_start_max_x}
        {\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_clip_path_beyond_finish:}
%   Clip path for finishrange with finish beyond indicator.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_clip_path_beyond_finish:
  {
    \@@_debug:n{~Finish~clip~path:~finishrange,~beyond~finish}
    \pgfmathsetmacro{\l_@@_tmpa_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_finishrange_finish_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpb_pgf}{
      .5*\l_@@_tmpa_pgf
    }
    \pgfpathmoveto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {90}
      {270}
      {\l_@@_finish_beyond_x_radius_pgf
        ~and~\l_@@_tmpb_pgf}
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpa_pgf}
      }
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finish_min_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finish_min_x}
        {-\l_@@_bar_thickness_pgf}
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Startrange/finishrange clipping paths with `opposite side' beyond indicator}
%
% \begin{macro}{\@@_interval_startrange_clip_path_beyond_finish:}
%   Clip path for startrange with finish beyond indicator. This macro should only be executed as
%   \cs{@@_interval_both_clip_path:} and specifies a complete path.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_clip_path_beyond_finish:
  {
    \@@_debug:n{~Two-sided~clip~path:~startrange,~beyond~finish}
    \pgfmathsetmacro{\l_@@_tmpc_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_startrange_finish_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpd_pgf}{
      .5*\l_@@_tmpc_pgf
    }
    \pgfpathmoveto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_beyond_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpc_pgf}
      }
    }
    \pgfpatharc
      {90}
      {270}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_tmpd_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_start_min_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_start_min_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpc_pgf}
      }
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_clip_path_beyond_start:}
%   Clip path for finishrange with start beyond indicator. This macro should only be executed as
%   \cs{@@_interval_both_clip_path:} and specifies a complete path.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_clip_path_beyond_start:
  {
    \@@_debug:n{~Two-sided~clip~path:~finishrange,~beyond~start}
    \pgfmathsetmacro{\l_@@_tmpc_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_finishrange_start_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpd_pgf}{
      .5*\l_@@_tmpc_pgf
    }
    \pgfpathmoveto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_beyond_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpc_pgf}
      }
    }
    \pgfpatharc
      {-90}
      {90}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_tmpd_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finish_max_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_interval_finish_max_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpc_pgf}
      }
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Startrange/finishrange clipping paths with `both sides' beyond indicator}
%
% \begin{macro}{\@@_interval_startrange_clip_path_beyond_both:}
%   Clip path for startrange with start and finish beyond indicators. This macro should only be executed as
%   \cs{@@_interval_both_clip_path:} and specifies a complete path.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_startrange_clip_path_beyond_both:
  {
    \@@_debug:n{~Two-sided~clip~path:~startrange,~beyond~both}
    \pgfmathsetmacro{\l_@@_tmpa_pgf}{
      \l_@@_bar_thickness_pgf
      *\l_@@_interval_startrange_start_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpb_pgf}{
      .5*\l_@@_tmpa_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpc_pgf}{
      \l_@@_bar_thickness_pgf
      *\l_@@_interval_startrange_finish_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpd_pgf}{
      .5*\l_@@_tmpc_pgf
    }
    \pgfpathmoveto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_beyond_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpc_pgf}
      }
    }
    \pgfpatharc
      {90}
      {270}
      {\l_@@_finish_beyond_x_radius_pgf
        ~and~\l_@@_tmpd_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {-90}
      {90}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_tmpb_pgf}
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpa_pgf}
      }
    }
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{\l_@@_tmpc_pgf}
      }
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_finishrange_clip_path_beyond_both:}
%   Clip path for finishrange with start and finish beyond indicators. This macro should only be executed as
%   \cs{@@_interval_both_clip_path:} and specifies a complete path.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_finishrange_clip_path_beyond_both:
  {
    \@@_debug:n{~Two-sided~clip~path:~finishrange,~beyond~both}
    \pgfmathsetmacro{\l_@@_tmpa_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_finishrange_finish_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpb_pgf}{
      .5*\l_@@_tmpa_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpc_pgf}{
      \l_@@_bar_thickness_pgf
        *\l_@@_interval_finishrange_start_level_pgf
    }
    \pgfmathsetmacro{\l_@@_tmpd_pgf}{
      .5*\l_@@_tmpc_pgf
    }
    \pgfpathmoveto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_beyond_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpc_pgf}
      }
    }
    \pgfpatharc
      {-90}
      {90}
      {\l_@@_start_beyond_x_radius_pgf
        ~and~\l_@@_tmpd_pgf}
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_start_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_thickness_pgf}
    }
    \pgfpathlineto{
      \pgfpoint
        {\l_@@_finish_beyond_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfpatharc
      {90}
      {270}
      {\l_@@_finish_beyond_x_radius_pgf
        ~and~\l_@@_tmpb_pgf}
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_finish_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpa_pgf}
      }
    }
    \pgfpathlineto{
      \pgfpointadd{
        \pgfpoint
          {\l_@@_start_x}
          {\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint{0}{-\l_@@_tmpc_pgf}
      }
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \paragraph{Core clipping macros}
%
% \begin{macro}{\@@_interval_clip:}
%   Clip the interval. The internal macro \cs{@@_interval_both_clip_path:} may be redefined from its default.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_clip:
  {
    \@@_debug:n{Clipping:}
    \pgfinterruptboundingbox
    \@@_interval_both_clip_path:
    \pgfpathclose
    \pgfusepath{clip}
    \endpgfinterruptboundingbox
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_both_clip_path:}
%   Specify a clipping path for the interval. If either of the macros \cs{@@_interval_start_clip_path:} is
%   \cs{@@_interval_finish_clip_path:} is defined, it is used, otherwise the respective defaults are used.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_both_clip_path:
  {
    \cs_if_exist_use:NF\@@_interval_finish_clip_path:
      { \@@_interval_finish_clip_path_none: }
    \cs_if_exist_use:NF\@@_interval_start_clip_path:
      { \@@_interval_start_clip_path_none: }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Marks}
%
%    \begin{macrocode}
\msg_new:nnn{timechart}{interval_mark_outside}
  { Ignoring~mark~outside~interval~definite~part~at~date~#1 }
%    \end{macrocode}
%
% \begin{macro}{\@@_interval_mark:}
%   Draw marks on an interval.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_mark:
  {
    \pgfscope
    \bool_if:NTF\l_@@_interval_start_beyond_bool
      {
        \pgfmathsetmacro{\l_@@_interval_mark_min_x}
          { max(\l_@@_interval_start_max_x,\l_@@_start_x) }
      }
      {
        \cs_set_eq:NN\l_@@_interval_mark_min_x\l_@@_interval_start_max_x
      }
    \bool_if:NTF\l_@@_interval_finish_beyond_bool
      {
        \pgfmathsetmacro{\l_@@_interval_mark_max_x}
          { min(\l_@@_interval_finish_min_x,\l_@@_finish_x) }
      }
      {
        \cs_set_eq:NN\l_@@_interval_mark_max_x\l_@@_interval_finish_min_x
      }
    \pgfsetstrokecolor{\l_@@_mark_color}
    \foreach \year in \l_@@_mark_text
      {
        \pgfmathsetmacro{\l_@@_mark_x}{yeartox(\year)}
        \@@_pgfmathsetbool:nn{\l_@@_tmpa_bool}
          {
            and (
              \l_@@_mark_x >= \l_@@_interval_mark_min_x,
              \l_@@_mark_x <= \l_@@_interval_mark_max_x
            )
          }
        \bool_if:NTF\l_@@_tmpa_bool
          {
            \pgfpathmoveto{
              \pgfpoint
                {\l_@@_mark_x}
                {-\l_@@_bar_half_thickness_pgf}
            }
            \pgfpathlineto{
              \pgfpoint
                {\l_@@_mark_x}
                {\l_@@_bar_half_thickness_pgf}
            }
            \pgfusepath{draw}
          }
          { \msg_warning:nne{timechart}{interval_mark_outside}{\year} }
      }
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Bar node}
%
% \begin{macro}{\@@_interval_define_bar_node:}
%   Define a node with into which the bar fits exactly.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_define_bar_node:
  {
    \@@_make_rectangle_node:nnnn
      {
        \pgfpoint
          {\l_@@_interval_start_min_x}
          {-\l_@@_bar_half_thickness_pgf}
      }{
        \pgfpoint
          {\l_@@_interval_finish_max_x}
          {\l_@@_bar_half_thickness_pgf}
      }
      {\pgfkeysvalueof{/timechart/interval~bar~node~name}}
      {\c_false_bool}
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsubsection{Label}
%
% \begin{macro}{\@@_interval_label:}
%   Place the label for the item.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_label:
  {
    \str_if_empty:NF \l_@@_label_text
      {
        \pgfinterruptboundingbox
        \int_case:nn {\l_@@_label_pos_int}
        {
          {0}{ \@@_interval_label_left: }
          {1}{ \@@_interval_label_center: }
          {2}{ \@@_interval_label_right: }
        }
        \endpgfinterruptboundingbox
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_label_left:}
%   Place the label on the left of the interval.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_label_left:
  {
    \@@_if_x_in_bounds:nT{\l_@@_interval_start_min_x}
      {
        \group_begin:
        \pgftransformshift{
          \pgfpoint
            {\l_@@_interval_start_min_x}
            {\l_@@_text_baseline_pgf}
        }
        \node[/timechart/interval~label,anchor=base~east]
          (\l_@@_interval_label_node_name)
          at (0,0)
          {
            \@@_make_ref:NN
              \l_@@_ref_text
              \l_@@_label_text
          };
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_label_right:}
%   Place the label on the right of the interval.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_label_right:
  {
    \@@_if_x_in_bounds:nT{\l_@@_interval_finish_max_x}
      {
        \group_begin:
        \pgftransformshift{
          \pgfpoint
            {\l_@@_interval_finish_max_x}
            {\l_@@_text_baseline_pgf}
        }
        \node[/timechart/interval~label,anchor=base~west]
          (\l_@@_interval_label_node_name)
          at (0,0)
          {
            \@@_make_ref:NN
              \l_@@_ref_text
              \l_@@_label_text
          };
        \group_end:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_interval_label_center:}
%   Place the label at the center of the interval.
%    \begin{macrocode}
\cs_new:Npn\@@_interval_label_center:
  {
    \pgfmathsetlengthmacro{\l_@@_label_anchor_x}
      {
        .5*max(\l_@@_interval_start_max_x,\l_@@_start_x)
        + .5*min(\l_@@_interval_finish_min_x,\l_@@_finish_x)
      }
%    \end{macrocode}
%   First draw the `background label' on the layer below the bar.
%    \begin{macrocode}
    \group_begin:
    \pgftransformshift{
      \pgfpoint
        {\l_@@_label_anchor_x}
        {\l_@@_text_baseline_pgf}
    }
    \pgfonlayer{labelbg}
    \node[
      /timechart/interval~label~centered~background,
      anchor=base
    ]
      at (0,0)
      { \l_@@_label_text };
    \endpgfonlayer
    \group_end:
%    \end{macrocode}
%   Then draw the label on top of the bar, clipping it to the bar outline.
%    \begin{macrocode}
    \pgfscope
    \pgfpathrectanglecorners{
      \pgfpoint
        {\l_@@_interval_start_min_x}
        {-\l_@@_bar_half_thickness_pgf}
    }{
      \pgfpoint
        {\l_@@_interval_finish_max_x}
        {\l_@@_bar_half_thickness_pgf}
    }
    \pgfusepath{clip}
    \group_begin:
    \pgftransformshift{
      \pgfpoint
        {\l_@@_label_anchor_x}
        {\l_@@_text_baseline_pgf}
    }
    \node[
    /timechart/interval~label~centered,
    anchor=base
    ]
      (\l_@@_interval_label_node_name)
      at (0,0)
      {
        \@@_make_ref:NN
        \l_@@_ref_text
        \l_@@_label_text
      };
    \group_end:
    \endpgfscope
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Text}
%
% \begin{macro}{\@@_text_user:Omm}
%   Place text. This macro will be made available as \cs{timecharttext} inside the \env{timechart} environment.
%   \begin{arguments}
%     \item PGF keys under \key{/timechart/} to apply.
%     \item Year at which to place text.
%     \item Text.
%   \end{arguments}
%    \begin{macrocode}
\NewDocumentCommand{\@@_text_user:Omm}{ O{} m m }
  {
    \str_if_empty:nF{#3}{
      \group_begin:
      \pgfmathsetmacro{\l_@@_text_x}{yeartox(#2)}
%    \end{macrocode}
%   Process keys supplied locally and retrieve initially needed keys.
%    \begin{macrocode}
      \pgfqkeys{/timechart}{
        #1,
        tolerance~start/.get=\l_@@_start_tolerance_pgf,
        tolerance~finish/.get=\l_@@_finish_tolerance_pgf,
      }
      \@@_if_x_in_bounds:nT{\l_@@_text_x}
        {
%    \end{macrocode}
%   Retrieve other needed keys.
%    \begin{macrocode}
          \pgfqkeys{/timechart}{
            ref/.get=\l_@@_ref_text,
            text~node~name/.get=\l_@@_node_name_text,
            text~baseline/.get=\l_@@_text_baseline_pgf,
          }
%    \end{macrocode}
%    Shift to the correct vertical coordinate and place the text.
%    \begin{macrocode}
          \pgftransformshift{
            \pgfpoint{0}{\l_@@_current_y}
          }
          \pgfinterruptboundingbox
          \group_begin:
          \pgftransformshift{
            \pgfpoint{\l_@@_text_x}{\l_@@_text_baseline_pgf}
          }
          \cs_set:Npn\l_@@_text{#3}
          \int_case:nn {\l_@@_text_pos_int}
          {
            {0}{ \cs_set:Npn\l_@@_node_anchor_text{base~east} }
            {1}{ \cs_set:Npn\l_@@_node_anchor_text{base} }
            {2}{ \cs_set:Npn\l_@@_node_anchor_text{base~west} }
          }
          \node[/timechart/text,anchor=\l_@@_node_anchor_text]
            (\l_@@_node_name_text)
            at (0,0)
            {
              \@@_make_ref:NN
              \l_@@_ref_text
              \l_@@_text
            };
          \group_end:
          \endpgfinterruptboundingbox
        }
      \group_end:
    }
%    \end{macrocode}
%   Since the text itself does not affect the bounding box, create a space (which will handle the automatic step).
%    \begin{macrocode}
    \@@_space_user:O[#1]
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Space}
%
% \begin{macro}{\@@_space_user:O}
%   Create a vertical space as if there were an interval at the current coordinate. This macro will be made available as
%   \cs{timechartspace} inside the \env{timechart} environment.
%    \begin{macrocode}
\NewDocumentCommand{\@@_space_user:O}{ O{} }
  {
    \group_begin:
%    \end{macrocode}
%   Process keys supplied locally and retreive the one needed value.

%    \begin{macrocode}
    \pgfqkeys{/timechart}{
      #1,
      interval~bar~thickness/.get=\l_@@_bar_thickness_pgf,
    }
    \pgfmathsetlengthmacro{\l_@@_bar_half_thickness_pgf}
      { .5*\l_@@_bar_thickness_pgf }
%    \end{macrocode}
%    Shift to the correct vertical coordinate and create the space.
%    \begin{macrocode}
    \pgftransformshift{
      \pgfpoint{0}{\l_@@_current_y}
    }
    \pgfpathmoveto{
      \pgfpoint{0}{-\l_@@_bar_half_thickness_pgf}
    }
    \pgfpathmoveto{
      \pgfpoint{0}{\l_@@_bar_half_thickness_pgf}
    }
    \pgfusepath{discard}
    \group_end:
    \bool_if:NT\l_@@_autostep_bool{
      \@@_step_y_user:O
    }
  }
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Legends}
%
% \begin{macro}{\timechartlegenditem}
%   Draw a bar suitable for use in a legend, applying style in \param{1}.
%    \begin{macrocode}
\NewDocumentCommand{\timechartlegenditem}{ O{} }
  {
    \@@_legend_aux:nn{#1}{
      \pgfmathsetlengthmacro{\l_@@_interval_solid_start_x}{0}
      \pgfmathsetlengthmacro{\l_@@_interval_solid_finish_x}
        {\l_@@_legenditem_width_pgf}
      \@@_interval_solid_draw:
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\timechartlegendstartrange,\timechartlegendfinishrange}
%   Draw a bar with start/finish range, suitable for use in a legend, applying style in \param{1}.
%    \begin{macrocode}
\NewDocumentCommand{\timechartlegendstartrange}{ O{} }
  {
    \@@_legend_aux:nn{#1}{
      \pgfmathsetlengthmacro
        {\l_@@_interval_startrange_start_x}{0}
      \pgfmathsetlengthmacro{\l_@@_interval_startrange_finish_x}
        {\l_@@_legenditem_range_width_pgf}
      \pgfmathsetlengthmacro
        {\l_@@_interval_startrange_start_level_pgf}{0}
      \pgfmathsetlengthmacro
        {\l_@@_interval_startrange_finish_level_pgf}{1}
      \pgfmathsetlengthmacro{\l_@@_interval_solid_finish_x}
        {\l_@@_legenditem_width_pgf}
      \int_case:nn {\l_@@_start_range_type_int}
        {
          {0}{
            \pgfmathsetlengthmacro{\l_@@_interval_solid_start_x}
              {\l_@@_legenditem_range_width_pgf}
            \@@_interval_startrange_draw_pseudofade:
          }
          {1}{
            \pgfmathsetlengthmacro{\l_@@_interval_solid_start_x}
              {\l_@@_interval_startrange_start_x}
            \pgfinterruptboundingbox
            \@@_interval_finish_clip_path_none:
            \@@_interval_startrange_clip_path_start:
            \pgfpathclose
            \pgfusepath{clip}
            \endpgfinterruptboundingbox
          }
        }
      \@@_interval_solid_draw:
    }
  }
\NewDocumentCommand{\timechartlegendfinishrange}{ O{} }
  {
    \@@_legend_aux:nn{#1}{
      \pgfmathsetlengthmacro{\l_@@_interval_finishrange_start_x}
        {
          \l_@@_legenditem_width_pgf
          -\l_@@_legenditem_range_width_pgf
        }
      \pgfmathsetlengthmacro{\l_@@_interval_finishrange_finish_x}
        {\l_@@_legenditem_width_pgf}
      \pgfmathsetlengthmacro
        {\l_@@_interval_finishrange_start_level_pgf}{1}
      \pgfmathsetlengthmacro
        {\l_@@_interval_finishrange_finish_level_pgf}{0}
      \pgfmathsetlengthmacro
        {\l_@@_interval_solid_start_x}{0}
      \pgfmathsetlengthmacro{\l_@@_interval_finish_max_x}
        {\l_@@_legenditem_width_pgf}
      \int_case:nn {\l_@@_finish_range_type_int}
        {
          {0}{
            \pgfmathsetlengthmacro{\l_@@_interval_solid_finish_x}
              {
                \l_@@_legenditem_width_pgf
                -\l_@@_legenditem_range_width_pgf
              }
            \@@_interval_finishrange_draw_pseudofade:
          }
          {1}{
            \pgfmathsetlengthmacro{\l_@@_interval_solid_finish_x}
              {\l_@@_interval_finishrange_finish_x}
            \pgfinterruptboundingbox
            \@@_interval_finishrange_clip_path_finish:
            \@@_interval_start_clip_path_none:
            \pgfpathclose
            \pgfusepath{clip}
            \endpgfinterruptboundingbox
          }
        }
      \@@_interval_solid_draw:
    }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_legend_aux:nn}
%   Auxiliary command for legend items. Draw a \TikZ\ picture, applying PGF keys \param{1} under \key{/timechart/}
%   and using \TikZ\ code \param{2}.
%    \begin{macrocode}
\cs_new:Npn\@@_legend_aux:nn #1#2
  {
    \@@_debug:n{Legend~auxiliary}
    \tikzpicture
%    \end{macrocode}
%   Process supplied PGF keys and retrieve only those necessary.
%    \begin{macrocode}
    \pgfkeys{
      /timechart/.cd,
      #1,
      interval~bar~thickness/.get=\l_@@_bar_thickness_pgf,
      interval~bar~color/.get=\l_@@_bar_color,
      interval~minimum~width/.get=\l_@@_minimum_width_pgf,
      beyond~length~start/.get=\l_@@_start_beyond_length_pgf,
      beyond~length~finish/.get=\l_@@_finish_beyond_length_pgf,
      legend~item~width/.get=\l_@@_legenditem_width_pgf,
      legend~item~range~width/.get=\l_@@_legenditem_range_width_pgf,
    }
    \pgfmathsetlengthmacro{\l_@@_bar_half_thickness_pgf}
      {.5*\l_@@_bar_thickness_pgf}
    \pgfmathsetmacro{\l_@@_start_x}{0}
    \pgfmathsetmacro{\l_@@_finish_x}
      {\l_@@_legenditem_width_pgf}
    \pgfmathsetlengthmacro{\l_@@_start_beyond_x}
      {\l_@@_start_x-\l_@@_start_beyond_length_pgf}
    \pgfmathsetlengthmacro{\l_@@_finish_beyond_x}
      {\l_@@_finish_x+\l_@@_finish_beyond_length_pgf}
    \pgfmathsetmacro{\l_@@_current_y}{0}
%    \end{macrocode}
%   Ensure that the legend is `visible' from the perspective of the drawing macros.
%    \begin{macrocode}
    \pgfmathsetmacro{\l_@@_start_tolerance_x}
      {\l_@@_start_x-10mm}
    \pgfmathsetmacro{\l_@@_finish_tolerance_x}
      {\l_@@_finish_x+10mm}
    \pgfscope
    #2
    \endpgfscope
    \endtikzpicture%
  }
%    \end{macrocode}
% \end{macro}
%
%
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
%
%
%
% \iffalse
%<*metadriver>
\input{timechart.dtx}
%</metadriver>
% \fi
