I'm sure this is possible with datetime
or datetime2
but here's a start with the PGFCalendar package.
Its \pgfcalendardatetojulian
macro is used to convert a date in y-m-d[+Δ] format into an integer which can be used to calculate the difference between dates very easily.
The macro \pgfcalendarjuliantodate
does the opposite and will be used to also store the year, month and date of each date.
The PGFKeys package that's loaded by PGFCalendar anyway is used to store the dates.
I've included some error handling.
You can adjust the macros \printdate
and \printdays
as you wish. While pgfcalendar
has support for conversion of month numbers into month names and translation via the translator
and babel
package, the babel
package has some date printing facilities of its own.
Code
\documentclass{article}
\usepackage{pgfcalendar}
% adjust these for babel (\localedate), siunitx (\qty), …
\newcommand*\printdate[3]{\pgfcalendarmonthname{#2} #3, #1}
\newcommand*\printdays[1]{#1}
\makeatletter
\newcommand*\newdate[2]{%
\pgfcalendardatetojulian{#2}{\count@}%
\pgfcalendarjuliantodate{\count@}{\Year}{\Month}{\Day}%
\pgfkeyssetevalue{/storydates/#1}{\the\count@}%
\pgfkeyssetevalue{/storydates/#1/ymd}{{\Year}{\Month}{\Day}}%
\ignorespaces}
\newcommand*\setdate[2]{%
\pgfkeysifdefined{/storydates/#2}{%
\pgfkeysgetvalue{/storydates/#2}\@temp
\pgfkeyslet{/storydates/#1}\@temp
\pgfkeysgetvalue{/storydates/#2/ymd}\@temp
\pgfkeyslet{/storydates/#1/ymd}\@temp
}{% Warning and Fallback
\PackageWarning{story dates}{Date #2 not defined.}%
\newdate{#1}{\year-\month-\day}}%
\ignorespaces}
\newcommand*\displaydate[1]{%
\pgfkeysgetvalue{/storydates/#1/ymd}\@temp
\expandafter\printdate\@temp}
\makeatother
\newcommand*\addtodate[2]{%
\pgfkeysifdefined{/storydates/#1}{%
\pgfkeyssetevalue{/storydates/#1}
{\the\numexpr\pgfkeysvalueof{/storydates/#1}+#2\relax}%
\pgfcalendarjuliantodate{\pgfkeysvalueof{/storydates/#1}}{\Year}{\Month}{\Day}%
\pgfkeyssetevalue{/storydates/#1/ymd}{{\Year}{\Month}{\Day}}%
}{% Warning and Fallback
\PackageWarning{story dates}{Date #1 not defined.}%
\newdate{#1}{\year-\month-\day+#2}}%
\ignorespaces}
\newcommand*\dateDifference[2]{%
\pgfkeysifdefined{/storydates/#1}{%
\pgfkeysifdefined{/storydates/#2}{%
\expandafter\printdays\expandafter{\the\numexpr\pgfkeysvalueof
{/storydates/#1}-\pgfkeysvalueof{/storydates/#2}\relax}%
}{\PackageWarning{story dates}{Date #2 not defined.}}%
}{\PackageWarning{story dates}{Date #1 not defined.}}}
\begin{document}
\newdate{startOfStory}{1900-01-01}
\setdate{fictionalNow}{startOfStory}
\addtodate{fictionalNow}{42}
\newdate{eventX}{1905-10-12}
On \displaydate{eventX}, \dateDifference{eventX}{fictionalNow}
days after \displaydate{fictionalNow} \dots
\end{document}
Output
On October 12, 1905, 2068 days after February 12, 1900 …
pgfcalendar
withpgfmath
or just with counters/TeX calculations. Once you have the Julian date number, it's easy to add 42 or whatever just using LaTeX\addtocounter...
. (2) ctan.org/pkg/datenumber. If you look at packages for creating timetables for e.g. teaching you can see how to manipulate the dates since many of them work by, for example, setting a start date and then adding so many days between classes. If you want more help, please post a complete MWE.