TeX Alchemist Online

TeX のこと,フォントのこと,Mac のこと

来年の教材変更を予約する

TeX & LaTeX Advent Calendar 20234日目の記事で,日付演算の方法について解説しました。

doratex.hatenablog.jp

今回はそれを実務に応用してみましょう。

実務上の発生状況例

教材作成業務をしていると,次のような場面に遭遇することが珍しくありません。

  • 授業テキストは印刷所に入稿して製本し,解答はプリンタで印刷して授業の場で紙として配布する授業運営形態であるとする。
  • 例えば数学のテキストで,例題として

    命題○○を数学的帰納法を用いて証明せよ。

という問題を掲載して配布した。この「数学的帰納法を用いて」という部分は,「帰納法を用いると解けるよ」というヒントのつもりで付されている文言であった。

  • ところがその後,帰納法を用いずにもっとエレガントに証明できる別解が見つかった。すると,この問題文の「数学的帰納法を用いて」という部分は,「筋の悪い解法指定の誘導」ということになってしまう。

  • だが,今年のテキストは既に入稿・配布してしまっており,生徒はそれで予習してきている以上,今年の授業での配布解答としては,帰納法を用いた解法を本解として掲載せざるを得ない。

  • 来年以降は,問題文から「数学的帰納法を用いて」という文言は削除し,配布解答も帰納法を使わない解法を本解とし,帰納法を使う解答は別解に格下げしたい。だが,1年待つのでは,来年その改訂作業をするのを忘れそうなので,覚えているうちに今すぐその改訂作業をしたい。

欲しい機能

上記のような場面において,

  • 今年コンパイルすると帰納法を使う解法が本解になる
  • 来年コンパイルすると,問題文から解法指定の文言が消えると同時に,解答においては帰納法が別解に格下げされる

という機構があると,来年の作業忘れが防げます。つまり,

  • 来年の教材改訂を今のうちに予約しておく
  • 来年コンパイルすると勝手にコンパイル内容が変わる

という仕組み,というわけです。

このようなとき,前記事で作成した,日付からユリウス通日へと変換する仕組みがあれば,「現在の日付に応じてコンパイル結果を変える」ということが可能になります。これにより,将来の教材改訂を今のうちに予約しておくというわけです。

例えば,次のような仕様のコマンドを定義しましょう。

\時限実行{#1}{#2}{#3}{#4}
% #1: 開始日付(年/月/日 の形式の文字列,空文字列ならば -∞ 扱い)
% #2: 終了日付(年/月/日 の形式の文字列,空文字列ならば +∞ 扱い)
% #3: 今日が [#1, #2] に属している場合に実行する処理
% #4: そうでないときに実行する処理

例えば次のような形式で使います。

\時限実行{2023/4/1}{2024/3/31}{今は2023年度内です。}{今は2023年度内ではありません。}

実装例

前記事で定義したコマンド群も含めて,実装例を Gist に置いておきました。

追記:より単純な実装

確かに,今回のように「日付の前後関係を判定する」だけであれば,より単純に,YYYYMMDD の8桁整数の大小を比較するだけで十分ですね。その方針で,\時限実行 を再実装してみると,次のようになります。

%#!uplatex
\documentclass[autodetect-engine,dvipdfmx]{jsarticle}
\makeatletter
\usepackage{ifthen}

\def\dateToYYYYMMDD#1{\@dateToYYYYMMDD#1\@nil}
\def\@dateToYYYYMMDD#1/#2/#3\@nil{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3\relax}

\newcount\@startDate
\newcount\@endDate
\newcount\@currentDate

\newcommand\時限実行[4]{%
  \if"#1"\@startDate=-1\else
    \@startDate=\dateToYYYYMMDD{#1}%
  \fi
  \if"#2"\@endDate=99999999\else
    \@endDate=\dateToYYYYMMDD{#2}%
  \fi
  \@currentDate=\dateToYYYYMMDD{\the\year/\the\month/\the\day}%
  \ifthenelse{\@currentDate<\@startDate\OR\@currentDate>\@endDate}{#4}{#3}%
}
\makeatother

\begin{document}

% 今日の日付に応じて出力を変える

% 区間[#1,#2]に属するか否かで場合分け
\時限実行{2023/4/1}{2024/3/31}{今は2023年度内です。}{今は2023年度内ではありません。}\par
\時限実行{2024/4/1}{2025/3/31}{今は2024年度内です。}{今は2024年度内ではありません。}\par

% 区間(-∞,#2]に属するか否かで場合分け
\時限実行{}{2023/3/31}{まだ2023年度が到来していません。}{既に2023年度は到来しました。}\par
\時限実行{}{2024/3/31}{まだ2024年度が到来していません。}{既に2024年度は到来しました。}\par

% 区間[#1,+∞)に属するか否かで場合分け
\時限実行{2023/4/1}{}{既に2023年度は到来しました。}{まだ2023年度が到来していません。}\par
\時限実行{2024/4/1}{}{既に2024年度は到来しました。}{まだ2024年度が到来していません。}\par

\end{document}

ユーザからの入力が,2023/4/1 のように,月・日が必ずしも2桁整数とは限らない整数で与えられることを想定して,

#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3\relax

の部分で zero padding している点に注目しましょう。「#2が10未満なら 0 を1つ打つ」という形で zero padding しています。100 の間にスペースを入れることで,TeXインタプリタ側に対して整数リテラルの終結を伝えることがポイントですね。