MTタグで日時を比較する方法とMTDateタグとtsモディファイア
日時の比較は数値を比較するようにMTIf
タグで行います。
値の大きい方が未来、小さい方が過去になります。
<$MTSetVar name="foo" value="2000年9月 9日 01:00"$>
<$MTSetVar name="bar" value="2000年9月13日 01:00"$>
<MTIf name="foo" lt="$bar">
<$MTGetVar name="foo"$> より <$MTGetVar name="bar"$> の方が未来です
<MTElse name="bar" lt="$foo">
<$MTGetVar name="bar"$> より <$MTGetVar name="foo"$> の方が未来です
</MTIf>
2000年9月 9日 01:00 より 2000年9月13日 01:00 の方が未来です
ところがどっこい、正しい比較ができない場合もあります。
失敗例
比較の式は上記と同じなので省略します。
その一。
<$MTSetVar name="foo" value="2000年9月9日"$>
<$MTSetVar name="bar" value="2000年9月13日"$>
2000年9月13日 より 2000年9月9日 の方が未来です
その二。
<$MTSetVar name="foo" value="Wed, 13 Sep 2000 01:00:00 +0900"$>
<$MTSetVar name="bar" value="Thu, 14 Sep 2000 01:00:00 +0900"$>
Thu, 14 Sep 2000 01:00:00 +0900 より Wed, 13 Sep 2000 01:00:00 +0900 の方が未来です
比較可能な条件
以上の成功例と失敗例から次のような条件が必要だと考えられます。
- 日時は桁数が同一である
- 日時は数字以外の部分が同一である
この条件を満たしていないと数値の比較ではなく、文字列の比較(ソート)になってしまうのだと思います。
条件さえ満たしていれば、次のような比較も可能です。
<MTIf tag="EntryDate" gt="Date">
この記事は未来のものです
<MTElse tag="EntryDate" lt="Date">
この記事は過去のものです
<MTElse tag="EntryDate" eq="Date">
この記事は現在のものです
</MTIf>
この場合は日付の言語のフォーマットで比較されています。
それでは、月名を含む言語のlanguage="en"
や曜日名を含むformat_name="rfc822"
の出力形式をした日時は比較できないのでしょうか。
<$MTSetVar name="foo" value="September 13, 2000 1:00 AM"$>
<$MTSetVar name="bar" value="Wed, 13 Sep 2000 01:00:00 +0900"$>
このままでは非常に難しいです。
(regex_replaceモディファイアで形式を変換すれば可能だと思います、非常に手間ですが)
しかし出力する前なら、先に日時を比較、後で任意の形式に出力、する方法があります。
そのためにはMTDate
タグの利用が不可欠です。
MTDate
タグとts
モディファイア
MTDate
タグには、任意の時間を任意の形式に出力できる、ts
モディファイアがあります。
ts="YYYYMMDDhhmmss"
値に指定した日付を利用して、任意のフォーマットで出力できます。設定する日付は
YYYYMMDDhhmmss
というフォーマットで記述します。
設定するフォーマットにさえ注意すれば難しくはありません。
<$MTDate ts="20000913010000" language="ja"$>
2000年9月13日 01:00
設定には変数の値を参照する事もできます。
<$MTSetVar name="second_impact" value="20000913010000"$>
<$MTDate ts="$second_impact" language="ja"$>
format="%Y%m%d%H%M%S"
ts
モディファイアのフォーマットをformat
モディファイアで用意すれば、他のMT*Date
タグの値も簡単に扱えます。
<$MTEntryDate format="%Y%m%d%H%M%S" setvar="date"$>
<$MTDate ts="$date" language="ja"$>
(す、すみません。良い例が考え付きませんでした)
MTDate
タグを利用した日時比較の例
先の失敗例もMTDate
タグを使えばこの通りです。
<$MTSetVar name="foo" value="20000913010000"$>
<$MTSetVar name="bar" value="20000914010000"$>
<MTIf name="foo" lt="$bar">
<$MTDate ts="$foo" format_name="rfc822"$> より <$MTDate ts="$bar" format_name="rfc822"$> の方が未来です
<MTElse name="bar" lt="$foo">
<$MTDate ts="$bar" format_name="rfc822"$> より <$MTDate ts="$foo" format_name="rfc822"$> の方が未来です
</MTIf>
Wed, 13 Sep 2000 01:00:00 +0900 より Thu, 14 Sep 2000 01:00:00 +0900 の方が未来です
ts
モディファイアのフォーマットは数値のみなので、比較するのに便利で、任意のフォーマットに再変換しやすい事がさらに便利です。
最新25件のブログ記事から投稿日時が一番古い記事を探す方法
この場合は日時の比較を使わない方法もありますが、答え合わせができる例をと考えました。
まあ、管理画面でブログ記事を25件ずつ表示させればすぐに確認できるんですけどね。
で、まずは日時の比較を使わない方法を二つ。
<MTEntries sort_by="created_on" sort_order="descend" offset="24" lastn="1">
<p><$MTEntryTitle$></p>
<p><$MTEntryDate language="en"$></p>
</MTEntries>
<MTEntries sort_by="created_on" sort_order="descend" lastn="25">
<MTEntriesFooter>
<p><$MTEntryTitle$></p>
<p><$MTEntryDate language="en"$></p>
</MTEntriesFooter>
</MTEntries>
簡単な構造なので解説は省略です。
そして本題、日時の比較を使った方法です。
<MTEntries sort_by="created_on" sort_order="descend" lastn="25">
<MTEntriesHeader>
<$MTEntryTitle setvar="title"$>
<$MTEntryDate format="%Y%m%d%H%M%S" setvar="date"$>
</MTEntriesHeader>
<$MTEntryDate format="%Y%m%d%H%M%S" setvar="entry_date"$>
<MTIf name="entry_date" le="$date"$>
<$MTEntryTitle setvar="title"$>
<MTSetVarBlock name="date"><$MTGetVar name="entry_date"$></MTSetVarBlock>
</MTIf>
</MTEntries>
<p><$MTGetvar name="title"$></p>
<p><$MTDate ts="$date" language="en"$></p>
ざっくり解説すると、まずMTEntriesHeader
タグ中で暫定チャンピオンを決めます。
変数entry_date
は挑戦者です。
そして、MTIf
タグで対決、挑戦者が勝ったらチャンピオンの交代です。
先の方法と同じ結果が出力されれば、日時の比較ができている事になります。
最新25件のブログ記事から1週間以内に投稿した記事を除いて表示する方法
下記の方法は日時を比較するためのデモンストレーションであり、実用には向かない欠陥を抱えています。
(欠陥については解説の続きを参照して下さい)
先の場合と違って、今度は日時を比較しないと無理だと思います。
(MT4.27現在、MTEntries
タグでoffset
とdays
モディファイアの併用ができません)
<$MTDate format="%Y%m%d%H%M%S" setvar="date"$>
<$MTSetVar name="date" op="-" value="7000000"$>
<MTEntries sort_by="created_on" sort_order="descend" lastn="25">
<$MTEntryDate format="%Y%m%d%H%M%S" setvar="entry_date"$>
<MTIf name="entry_date" lt="$date"$>
<p><$MTEntryTitle$></p>
<p><$MTDate ts="$entry_date" language="ja"$></p>
</MTIf>
</MTEntries>
ざっくり解説します。
まず、MTDate
タグで現在の日時を変数date
に格納します。
そこからMTSetVar
タグで1週間分(7日)を引いて、比較する基準の日時が準備できます。
記事の投稿日時は同じ形式で変数entry_date
に格納します。
後は、MTIf
タグで投稿日時が基準より過去か判断し、過去であれば記事名と投稿日時を出力します。
欠陥
現在日時の1週間前を計算するのに、7000000
を引いているのが駄目です。
例えば、同様の方法で2000年9月13日の14日前を用意しようとすると次のようなコードになります。
<$MTSetVar name="date" value="20000901010000"$>
<$MTSetVar name="date" op="-" value="7000000"$>
<$MTDate ts="$date" language="ja"$>
実行するとあり得ない日時が出力されます。
2000年8月87日 01:00
ts
モディファイアのフォーマットは進法がごちゃまぜなので、あ、当たり前ですよね……。
……出直してきます。
コメント[2]
コメント投稿フォーム
コメントを投稿するにはJavaScirptが必要です。ブラウザのJavaScriptを有効にしてください。
こんにちは、天野と申します。
MTのプラグインを書いて公開したりしています。
いつも分かりやすいエントリーで参考になります。
さて、分かり易さのために分けて書かれているようでしたらすみません、
もしご存知でなければと思いコメントしてみます。
MTIf に tag モディファイアを指定した場合には、
他のモディファイアがそのまま渡されるので、以下の2行は、
-----------------------------------------------------------------
<$MTEntryDate format="%Y%m%d%H%M%S" setvar="entry_date"$>
<MTIf name="entry_date" lt="$date"$>
-----------------------------------------------------------------
このようにまとめることもできるなと思いました。
-----------------------------------------------------------------
<MTIf tag="EntryDate" format="%Y%m%d%H%M%S" lt="$date"$>
-----------------------------------------------------------------
その二行をまとめなかったのは、主義に基づくコーディングであり、ただの癖でもあります。
データを参照するMTタグは極力複数回使わないように変数化する主義です。
そうすればデータベースを参照する回数が減ると思っています。
例では最後に記事名と日時を出力するようにしています。
もしもその二行をまとめると、その後でMTEntryDateタグを使う必要があります。
まあ二回の参照を一回にしても効果は皆無なんでしょうけど。