คำถามและความคาดหวัง
ในขณะที่รูปแบบที่แท้จริงของคำถามนี้มีประโยชน์ในบริบท (ปี 1899) มันค่อนข้างคลุมเครือเล็กน้อยในทางทฤษฎี อายุเท่าไหร่ เราอาจต้องการไปไกลแค่ไหนในอดีต? แล้วอนาคตล่ะ
ตั้งแต่ WordPress ได้เริ่มต้นเป็นเครื่องมือสร้างบล็อกในบริบทนั้นมันมีวิวัฒนาการในการจัดการกับช่วงเวลาต่อไปนี้:
- มีวันที่ WP อยู่ (เห็นได้ชัดว่าสามารถใช้งานได้)
- ช่วงของการโพสต์ทางประวัติศาสตร์ที่เป็นไปได้ (โดยปริยายไกลเท่าที่อินเทอร์เน็ตมีอยู่)
- เท่าที่เป็นไปได้ในอนาคตโดยไม่ต้องใช้ความพยายามพิเศษ (ทำงานจนกว่ามันจะหยุดพัก)
เนื่องจากการใช้งาน WordPress กลายเป็นแอพพลิเคชั่นที่ไม่บล็อกเช่นโครงการ (ประวัติศาสตร์และศิลปะที่ฉันเห็นจากรายงาน) เริ่มมีปัญหาหลายอย่างกับวันที่อยู่นอกช่วงนี้
เพื่อวัตถุประสงค์ในการวิจัยของฉันฉันได้กำหนดคำถามต่อไปนี้:
- ปีปฏิทินและปีปฏิทินล่าสุดที่เก่าและใหม่ซึ่งสามารถใช้กับวันที่โพสต์ WordPress ได้อย่างน่าเชื่อถือ?
- อะไรคือผลไม้แขวนลอยต่ำ (ถ้ามี) เพื่อขยายช่วงที่ใช้ได้มากกว่าช่วงดั้งเดิม?
ข้อ จำกัด ของแพลตฟอร์ม
เนื่องจาก WordPress เป็นแอปพลิเคชั่น PHP และใช้ MySQL ในการจัดเก็บข้อมูลจึงมีข้อ จำกัด
MySQL
WordPress เก็บวันที่โพสต์ในpost_date
คอลัมน์DATETIME
ประเภทใน MySQL
ตามเอกสารประเภทนี้สนับสนุนปี1,000 ถึง 9999 :
DATETIME
ชนิดที่ใช้สำหรับค่าที่มีทั้งวันที่และเวลาส่วน MySQL ดึงและแสดงDATETIME
ค่าใน'YYYY-MM-DD HH:MM:SS'
รูปแบบ ช่วงที่ได้รับการสนับสนุนในการ'1000-01-01 00:00:00'
'9999-12-31 23:59:59'
อย่างไรก็ตามมันยังบอกว่าค่าก่อนหน้านี้อาจใช้งานได้ไม่ต้องพูดถึงค่าในภายหลัง
สำหรับ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 บิต) นอกจากนี้บางแพลตฟอร์มไม่สนับสนุนการประทับเวลาเชิงลบดังนั้นช่วงวันที่ของคุณอาจถูก จำกัด ไว้ไม่เกิน Epoch ของ Unix ซึ่งหมายความว่าเช่นวันที่ก่อนหน้าJan 1, 1970
นี้จะไม่ทำงานบน Windows การแจกจ่าย Linux บางระบบและระบบปฏิบัติการอื่น ๆ PHP 5.1.0 และเวอร์ชันที่ใหม่กว่าเอาชนะข้อ จำกัด นี้ได้
นอกเหนือDate/Time
จากการจัดการที่ใหม่กว่านั้นคือ 64 บิตและมีช่วงประมาณ -292 พันล้านถึง 292 พันล้านปีซึ่งอาจเกินความต้องการของมนุษยชาติในขณะนี้
ข้อ จำกัด ของ WordPress
WordPress แนะนำและสืบทอดข้อ จำกัด เพิ่มเติมบางประการในฐานของรหัส
การไหลของข้อมูล
จากมุมมองเวิร์กโฟลว์ผู้ใช้ขั้นพื้นฐานมีการประมวลผลสองรายการที่เกี่ยวข้องกับวันที่:
- ป้อนวันที่ในแบบฟอร์มแก้ไขโพสต์จะต้องดำเนินการอย่างถูกต้องและบันทึกไว้ในฐานข้อมูล
- วันที่บันทึกในฐานข้อมูลจะต้องอ่านและแสดงอย่างถูกต้องในส่วนต่อประสาน
โปรดทราบว่าสิ่งเหล่านี้เป็นกระบวนการทางเทคนิคที่แตกต่างและเป็นอิสระอย่างสมบูรณ์ ตามที่อธิบายเพิ่มเติมช่วงของพวกเขาไม่ทับซ้อนกันและการบันทึกวันที่ที่ถูกต้องไม่เท่ากับความสามารถในการอ่านอย่างถูกต้องในสภาพแวดล้อม WordPress
ข้อ จำกัด ที่ชัดเจน
- บรรณาธิการโพสต์ WordPress ในผู้ดูแลระบบอนุญาตให้ช่วงของปีที่สามารถส่งเป็นวันที่โพสต์100 ถึง 9999
_wp_translate_postdata()
กระบวนการปี (ส่งเป็นตัวเลขที่แตกต่างจากแบบฟอร์ม) และ:
- ฆ่าเชื้อให้เป็น non-negative > 0
- ตรวจสอบความถูกต้องโดยใช้
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 โพสต์น่าจะเป็นเท่ากับว่า 32 บิตเวลา Unix และประกอบด้วยปี 1902-2037 อย่างครอบคลุม
สำหรับการดำเนินการวันที่โพสต์ใด ๆ ที่อยู่นอกช่วงของสภาพแวดล้อมนี้จะต้องได้รับการตรวจสอบ (ช่วง 64 บิตของการประทับเวลา Unix การทำงานของ MySQL หรือการจัดเก็บฐานข้อมูลสำรองสำหรับค่า) สำหรับช่วงที่ไกลออกไป ( ต่ำกว่า 1,000, มากกว่า 9999 ) รหัสที่กำหนดเองจำนวนมากน่าจะเป็นที่ต้องการ
สำหรับการติดตั้งวันที่ใด ๆ มันทำให้รู้สึกถึง:
- เก็บไว้ใน MySQL ในรูปแบบไม่ขึ้นอยู่กับข้อ จำกัด ของฐานข้อมูล
- กระบวนการใน PHP โดยใช้โค้ดที่กำหนดเองได้อย่างสมบูรณ์
Date/Time
และ / หรือฟังก์ชั่น 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,
) );
}
}