平衡点
2013/03/12
_ 日付の計算...?
TeX でじたばた
とある申請書のフォーマットを更新することになって, 今年から「申請第一希望日程」〜「申請第三希望日程」 という(感じの)項目が増えることに.
それ自体は良いのだけれど
- 開始日から終了日までの「期間」を求めて
- 三つの期間が等しい事を検証して, 等しくない場合には typeset を停止する
という処理を入れたい, という要望.
日付自体はソースから適当に持ってくれば良いのだけれど, \TeX (not \LaTeX ) で暦を計算する, というのは無理ゲーな気がするので, どうしようか思案 . ちなみに, 他の言語で日付だけ計算して, というのも(要件として)駄目.
結局
- 年度単位の申請書なので「総日数」を定義しておいて閏年判定に使用
- 入力された月日の経過総日数を計算, 差をとって区間を計算
としてみた.
とりあえず動いているから良しとするけれど, もっと上手い方法無いかなぁ.
日付のパース
入力が \start1={平成25年4月1日} みたいな塩梅なので, この入力値から年, 月, 日のみを取得する, みたいな.
# source: latex \def\YearElement#1年#2月#3日{#1} \def\MonthElement#1年#2月#3日{#2} \def\DayElement#1年#2月#3日{#3} \def\xYearElement#1{\expandafter\YearElement\the#1} \def\xMonthElement#1{\expandafter\MonthElement\the#1} \def\xDayElement#1{\expandafter\DayElement\the#1}
当然ながら, 文字コードが一致していないと駄目です. はい.
入力された月の日数を\tempdayカウンタに出力
- 閏年は 2 月が 29 日になる. それ以外は 28 日
- 7月以前(< 8) は, 奇数月が31日, 偶数月が30日
- 8月以降は, 奇数月が30日, 偶数月が31日
という塩梅で.
# source: latex \newcount\tempday \def\monthday#1{ \tempday=0 \ifnum#1=2 \ifnum\totalday>365 \tempday=29\relax \else \tempday=28\relax \fi \else \ifnum#1<8 \ifodd#1 \tempday=31\relax \else \tempday=30\relax \fi \else \ifodd#1 \tempday=30\relax \else \tempday=31\relax \fi \fi \fi }
入力された月からその月の前月までの経過日数を\TotalElapseDaysに出力
4月始まり, 翌年3月締なので, 1月から3月を13月から15月にして \loop する
# source: latex \newcount\tempmonth \newcount\TotalElapseDays \def\countTotalElapseDays#1{ \tempday=0 \TotalElapseDays=0 \tempmonth=#1\relax \monthday\tempmonth \advance \TotalElapseDays by - \tempday \ifnum\tempmonth<4 \advance\tempmonth by 12 \fi \loop \ifnum4<\tempmonth \ifnum\tempmonth>12 \ifnum\tempmonth=13\monthday1\fi \ifnum\tempmonth=14\monthday2\fi \ifnum\tempmonth=15\monthday3\fi \else \monthday\tempmonth \fi \advance\TotalElapseDays by \tempday \advance\tempmonth by - 1 \repeat }
入力された二つの月日から期間を計算して\Periodに出力
入力は{開始月日}{終了月日}といった塩梅
# source: latex \newcount\Period \newcount\tempcounter \def\calcPeriod#1#2{ \Period=0 \tempcounter=0 \tempcounter=\xMonthElement#2 \relax \countTotalElapseDays{\tempcounter} \Period=\TotalElapseDays \advance\Period by \xDayElement#2 \relax \tempcounter=\xMonthElement#1 \relax \countTotalElapseDays{\tempcounter} \advance\Period by - \TotalEpalseDays \advance\Period by - \xDayElement#1 \relax \advance\Pediod by 1 % 植木 }
うーん
とりあえずやりたかったことはできた訳ですが, なんというか. 手元の pTeX
This is pTeX, Version 3.1415926-p3.3 (utf8.euc) (TeX Live 2012/Debian) restricted \write18 enabled.
と pLaTeX
This is e-pTeX, Version 3.1415926-p3.3-110825-2.4 (utf8.euc) (TeX Live 2012/Debian) restricted \write18 enabled.
ではちゃんと動きましたが.
毎度ながら ad hoc.
どなたか \TeX で修正ユリウス通日とか計算するマクロとか もってらっしゃいませんかね?
(2013/03/13 微修正)
pgfという強大なグラフィックパッケージの中に<br> \pgfcalendardatetojulian{<date>}{<counter>}<br>というものがあったような気がします。マクロ使いではないので1時間ぐらい苦しみましたが<br> \newcount\mycounter<br> \pgfcalendardatetojulian{2013-03-13}{\mycounter}<br>とかして<br> \the\mycounter<br>とかで表示できました。<br>\pgfcalendarjuliantodate{2456365}{\myyear}{\mymonth}{\myday}<br>とかで逆変換もできて便利そうです。
pgf って、plain Tex で動くんでしたっけ?
追伸。<br>ついでに言うと pgf 持ってない古い TeX の人々のことも考える必要があったので、<br>pgfcalendar の存在は知っていたけれど、はなから考えてませんでした。<br>いまとなってはそっち見た方が良かったのかもしれませんね。