web-dev-qa-db-ja.com

ワードプレスで古い日付を選択できません

投稿の年を1899年未満に設定することはできません。年を1899より下に設定すると、自動的に現在の年に設定されます。

screen shot

Timeline テーマを購入し、彼らのサポートフォーラムで尋ねました。彼らは答えた:

これはあなたのホスティングプロバイダによって作成された制限のように聞こえます。テーマの中には、あなたが割り当てる日付を妨げるものは何もありません - ご覧のとおり、デモには1400年代の日付を使った投稿があります。あなたのホスティングプロバイダに連絡してみて、彼らがそれにどう対処するかについての洞察を持っているかどうかを確認してください。

12
Spartans

これは実際には答えではなく、単にこの問題の特定の状況を見つけようとする試みです。次のプラグインをあなたのサイトにインストールし、3つの日付を設定して下の表の2番目の<pre>に結果を追加してください。

/* Plugin Name: WPSE Sysinfo */
add_action( 'admin_footer', 'wpse_sysinfo' );
function wpse_sysinfo() {

    $bit         = 4 === PHP_INT_SIZE ? 32 : 64; // PHP version, not OS!
    $php_version = PHP_VERSION;
    $db_version  = $GLOBALS['wpdb']->db_version();

    print "<pre>$bit | $php_version | $db_version</pre>";
}

プラグインの要旨はここでチェックアウトすることができます

 OS | OSビットPHP | PHPビット| MySQL | 999 | 1899 | 2020 | 2039 |ユーザー
 WIN7 | 64 | 5.4.4 | ? | 5.5.25 | ☻| ☻| ✔| ☻| toscho 
 Linux | ? | 5.3.18-nmm1 | ? | 5.1.70 | ✔| ✔| ✔| ✔| toscho 
 CentOS 6 | 64 | 5.5.4 | ? | 5.0.95 | ✔| ✔| ✔| ✔| toscho 
 WIN7 | 64 | 5.4.15 | 32 | 5.5.31 | ☻| ☻| ✔| ☻|最初の
 Ubuntu 64 | 5.3.10-1 | 64 | 5.5.32 | ✔| ✔| ✔| ✔| Pille 
 CloudLinux | 64 | 5.2.17 | 64 | 5.0.96 | ✔| ✔| ✔| ✔|ピル
 Ubuntu 12.10 | 64 | 5.4.6 | 64 | 5.5.32 | ✔| ✔| ✔| ✔| Michael Ecklund 
 CENTOS 5.9 | 32 | 5.3.27 | 32 | 5.5.32 | ☻| ☻| ✔| ☻| Michael Ecklund 
 WIN7 | 64 | 5.4.7 | 64 | 5.5.27 | ☻| ☻| ✔| ☻|カイザー
 OSX 10.7.5 | 64 | 5.3.6 | 64 | 5.5.9 | ✔| ✔| ✔| ✔| GhostToast 
 Centos 6.4 | 64 | 5.4.17 | 32 | 5.1.59 | ☻| ☻| ✔| ☻| birgire 
 Debian 6 | 64 | 5.4.19 | 64 | 5.1.66 | ☻| ☻| ✔| ☻| birgire 
 WIN7 | 64 | 5.5.0 | 64 | 5.5.22 | ☻| ☻| ✔| ☻| G.M。
 OSX 10.7.4 | 64 | 5.3.6 | 64 | 5.5.9 | ✔| ✔| ✔| ✔|ブラソフィロ
 CentOS 5 | 64 | 5.3.22 | 64 | 5.1.68 | ✔| ✔| ✔| ✔| brasofilo 
マック10.8.5 | 64 | 5.3.26 | 64 | 5.5.25 | ✔| ✔| ✔| ✔| flentini 
 WIN7 | 64 | 5.3.27 | 64 | 5.5.31 | ✔| ✔| ✔| ✔| Sascha Krause 
 Win7SP1 | 64 | 5.3.8 | 64 | 5.5.28 | ✔| ✔| ✔| ✔| Manuel Sychold 
  1. 新しい投稿を作成してください。それを保存。
  2. 日付を1月1日に設定します。0999Updateをクリックします。保存されていますか、それとも現在の日付に変更されていますか?
  3. 18992020および2039の日付設定について繰り返します。
  4. 管理フッターのプラグイン出力から情報を取得して、テーブルを更新します。
10
fuxia

質問と期待

この質問の文字通りの形式は文脈において実用的ですが(1899年)、理論的な意味では少しあいまいです。何歳ですか? 行きたい過去はどれくらいですか?未来はどうですか?

WordPressはブログエンジンとして開始されたため、contextualの意味で、次の期間を処理するように進化しました。

  • 日付WPが存在した(明らかにそれを使用できるように)
  • 可能な履歴投稿の範囲(暗黙的にインターネットが存在した限り)
  • 特別な努力なしで、可能な限り未来まで(それが壊れるまで働く)

WordPressの使用が非ブログアプリケーションに進化したため、このようなプロジェクト(一般にレポートで見たような歴史と芸術)は、この期間外の日付でさまざまな問題に遭遇し始めました。

私の研究のために、私は次の質問を策定しました。

  1. WordPress投稿日付でネイティブかつ確実に使用できる、2つの最も早い完全な暦年とは何ですか?
  2. ネイティブレンジを超えて利用可能なスパンを拡張するために、ぶら下がっている果物(ある場合)とは何ですか?

プラットフォームの制限

WordPressはPHPアプリケーションであり、データストレージにMySQLを使用するため、制限があります。

MySQL

WordPressは、MySQLのDATETIMEタイプのpost_date列に投稿日を保存します。

ドキュメント によると、このタイプは年をサポートしています1000から9999

DATETIMEタイプは、日付と時刻の両方の部分を含む値に使用されます。 MySQLは'YYYY-MM-DD HH:MM:SS'形式でDATETIME値を取得して表示します。サポートされる範囲は'1000-01-01 00:00:00'から'9999-12-31 23:59:59'です。

ただし、以前の値mightが機能することもあり、後の値については言及されていません。

DATE and DATETIME範囲の説明の場合、「サポートされている」とは、以前の値が機能する可能性があるが、保証がないことを意味します。

経験的に、動作範囲外の値を観察しましたが、これは逸話であり、信頼性条件から外れています。

PHP

PHPプログラミングでは、日付のUnixタイムスタンプ表現が広く使用されています。 ドキュメント によると、目的(PHP 5.2+および一般的な32ビット環境)では、年(完全)をサポートしています1902から2037

タイムスタンプの有効な範囲は通常、Fri, 13 Dec 1901 20:45:54 UTCからTue, 19 Jan 2038 03:14:07 UTCです。 (これらは、32ビット符号付き整数の最小値と最大値に対応する日付です。)さらに、すべてのプラットフォームが負のタイムスタンプをサポートしているわけではないため、日付範囲はUnixエポック以前に制限される場合があります。これは、たとえばJan 1, 1970より前の日付は、Windows、一部のLinuxディストリビューション、および他のいくつかのオペレーティングシステムでは機能しません。 PHP 5.1.0以降のバージョンは、この制限を克服しています。

それ以外の Date/Time ベースのハンドリングは64ビットで、範囲はおよそ-292億から292億年であり、おそらく現時点で人類のニーズを超えています。

WordPressの制限

WordPressは、コードベースにいくつかの追加の制限を導入し、継承します。

データフロー

基本的なユーザーワークフローの観点から、日付に関連する2つの処理があります。

  • 編集後のフォームで入力された日付は、データベースで正しく処理および保存する必要があります
  • データベースに保存された日付が正しく読み取られ、インターフェースに表示される必要があります

これらは技術的に完全に異なる独立したプロセスであることに注意してください。さらに説明したように、それらの範囲は重複せず、正しい日付を保存することは、WordPress環境で正しく読み取る能力と等しくありません。

明示的な制限

  • 管理者のWordPress投稿エディターでは、投稿日として提出できる年数の範囲を許可しています100から9999
  • _wp_translate_postdata() 年を処理します(フォームとは異なる番号として送信されます)および:
    • 負でない>にサニタイズします
    • wp_checkdate() を使用して検証します。これは、PHPネイティブを呼び出します checkdate()1〜32767の制限を課します

暗黙の制限

  • strtotime() PHP関数は複数回使用され、上記のUnixタイムスタンプの対象となります。これは、データベースからの日付のすべての読み取りに影響する mysql2date() の最下位レベルです1902〜 2037範囲が継承されました
  • WordPressは get_gmt_from_date() での日付解析の正規表現にフォールバックします。これは年を([0-9]{1,4})と予想し、それを制限します1から9999、他の関数で同様の処理が必要になる可能性がありますより徹底的なコード監査を列挙する

回避策の可能性

  • wp_checkdate() にはwp_checkdateフィルターがあり、この検証チェックをオーバーライドできます
  • エンドユーザー向けの出力は date_i18n() を通過します。これにはdate_i18nフィルターがあり、理論的にはインターフェイスへの日付の出力を完全にインターセプトおよび再処理できますが、関数が既に範囲外に渡された場合は挑戦的です(false)タイムスタンプ入力

結論

データの実用的な目的と移植性のために、WordPress投稿日付範囲は2ビットUnixタイムスタンプの日付範囲と等しく、1902年から2037年まで包括的にのようです。

この範囲外の投稿日操作については、環境を監査する必要があります(64ビット範囲のUnixタイムスタンプ、デファクト機能のMySQL、または値の代替データベースストレージ)。それ以上の範囲(1000未満、9999以上)では、かなりの量のカスタムコードが必要になる可能性があります。

任意の日付の実装では、次のことを意味します。

  • データベースの制限を受けない形式でMySQLに保存する
  • 完全にカスタムのDate/Timeベースのコードおよび/またはPHP関数を使用してWordPressで処理し、Unixタイムスタンプ制限の影響を受けないように監査しました

コードテストベッド

次のコードと厳選された一連の年は、上記の調査と結論のテストに使用されています。

require ABSPATH . '/wp-admin/includes/post.php';

$timestamp_size_info = array(
    'PHP_INT_SIZE'   => PHP_INT_SIZE,
    'PHP_INT_MAX'    => number_format( PHP_INT_MAX ),
    'min timestamp'  => date( DATE_ISO8601, - PHP_INT_MAX ),
    'zero timestamp' => date( DATE_ISO8601, 0 ),
    'max timestamp'  => date( DATE_ISO8601, PHP_INT_MAX ),
);

r( $timestamp_size_info );

// hand picked set of years to test for assorted limits
$years = array(
    'negative'           => - 1,
    'zero'               => 0,
    'one'                => 1,
    'wp min'             => 100,
    'mysql first'        => 1000,
    'before unix'        => 1899,
    'unix first'         => 1902,
    'current'            => 2013,
    'unix last'          => 2037,
    'after unix'         => 2039,
    'mysql last, wp max' => 9999,
    'after checkdate'    => 33000,
);

// simulates form submission data
$post = array(
    'post_type' => 'post', // shut notice
    'edit_date' => 1,
    'aa'        => 1,
    'mm'        => '01',
    'jj'        => '01',
    'hh'        => '00',
    'mn'        => '00',
    'ss'        => '00',
);

// add_filter( 'wp_checkdate', '__return_true' );

foreach ( $years as $name => $year ) {

    $post['aa'] = $year;
    $translated = _wp_translate_postdata( false, $post );

    if ( is_wp_error( $translated ) ) { // wp_checkdate() failed
        r( array( 'year' => $year . " ({$name})", 'translated valid' => false ) );
    }
    else {

        $post_date        = $translated['post_date'];
        $post_date_gmt    = $translated['post_date_gmt'];
        $translated_valid = (string) $year == substr( $post_date, 0, strpos( $post_date, '-' ) );
        $mysql2date       = mysql2date( DATE_ISO8601, $post_date );
        $mysql2date_valid = (string) $year == substr( $mysql2date, 0, strpos( $mysql2date, '-' ) );

        r( array(
            'year'             => $year . " ({$name})",
            'post_date'        => $post_date,
            'translated valid' => $translated_valid,
            'post_date_gmt'    => $post_date_gmt,
            'mysql2date'       => $mysql2date,
            'from sql valid'   => $mysql2date_valid,
        ) );
    }
}
7
Rarst