질문과 기대
이 질문의 문자적인 형태는 맥락에서 실용적이지만 (1899 년) 이론적 인 의미로는 약간 모호합니다. 몇 살입니까? 얼마나 과거에 우리가 할 수 원하는 이동? 미래는 어떻습니까?
WordPress는 블로깅 엔진으로 시작한 이래 문맥 상 다음과 같은 시간 범위를 처리하도록 발전했습니다.
- WP가 존재하는 날짜 (분명히 사용할 수 있음)
- 가능한 과거 게시물 범위 (암시 적으로 인터넷이 존재하는 한)
- 특별한 노력없이 가능한 한 미래까지
WordPress 사용이 비 블로그 응용 프로그램으로 발전함에 따라 이러한 프로젝트 (보통 보고서에서 본 역사 및 예술)는이 범위를 벗어난 날짜와 관련하여 여러 가지 문제가 발생하기 시작했습니다.
연구 목적으로 다음과 같은 질문을 작성했습니다.
- WordPress 게시 날짜와 함께 기본적으로 안정적으로 사용할 수있는 가장 빠른 2 년의 연도 란 무엇입니까?
- 기본 범위 이상으로 사용 가능한 범위를 확장하기 위해 매달려있는 과일 (있는 경우)은 무엇입니까?
플랫폼 제한
WordPress는 PHP 응용 프로그램이며 데이터 저장을 위해 MySQL을 사용하기 때문에 제한이 있습니다.
MySQL
WordPress는 게시 날짜 를 MySQL 유형의 post_date
열에 저장 DATETIME
합니다.
문서 에 따르면 이 유형은 1000 ~ 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 프로그래밍에서 날짜의 유닉스 타임 스탬프 표현이 널리 사용됩니다. 우리의 목적 (PHP 5.2 + 및 일반 32 비트 환경)에 대한 문서 에 따르면 1902 ~ 2037 년 (전체)을 지원합니다 .
타임 스탬프의 유효 범위는 일반적으로 Fri, 13 Dec 1901 20:45:54 UTC
~ Tue, 19 Jan 2038 03:14:07 UTC
입니다. (이는 32 비트 부호있는 정수의 최소값과 최대 값에 해당하는 날짜입니다.) 또한 모든 플랫폼이 음수 타임 스탬프를 지원하지는 않으므로 날짜 범위가 유닉스 시대 이전으로 제한 될 수 있습니다. 즉, 이전 날짜 Jan 1, 1970
는 Windows, 일부 Linux 배포판 및 기타 일부 운영 체제에서는 작동하지 않습니다. PHP 5.1.0 및 최신 버전은이 한계를 극복합니다.
그 외에 새로운 Date/Time
기반 처리는 64 비트이며 대략 -292 십억에서 292 억년 사이 이며, 이는 현재 인류의 요구를 능가 할 것입니다.
워드 프레스 제한
워드 프레스는 코드베이스에 몇 가지 추가 제한을 도입하고 상속합니다.
데이터 흐름
기본 사용자 워크 플로 관점에서 날짜와 관련하여 처리 된 두 가지가 있습니다.
- 사후 편집 양식의 날짜 입력은 올바르게 처리되고 데이터베이스에 저장되어야합니다.
- 데이터베이스에 저장된 날짜를 올바르게 읽고 인터페이스에 표시해야합니다
이들은 기술적으로 완전히 다르고 독립적 인 프로세스입니다. 추가로 설명했듯이 범위가 겹치지 않으며 올바른 날짜를 저장하는 것이 WordPress 환경에서 올바르게 읽는 기능과 동일하지 않습니다.
명시 적 한계
암시 적 한계
strtotime()
PHP 함수는 여러 번 사용되며 위에서 언급 한 Unix 타임 스탬프에 종속됩니다. mysql2date()
데이터베이스에서 1902에서 2037 까지의 범위에서 상속 된 모든 날짜 읽기에 영향을 미치는 최저 수준
- 워드 프레스는 날짜 구문 분석을 위해 정규 표현식으로 돌아갑니다.
get_gmt_from_date()
연도는 1 ~ 9999로([0-9]{1,4})
제한 되며 다른 함수에서도 비슷한 처리가 가능해보다 철저한 코드 감사가 필요합니다.
대안의 가능성
wp_checkdate()
이 wp_checkdate
이 유효성 검사를 대체 할 수 필터,
- 필터 가있는 최종 사용자를 대상으로 한 출력
date_i18n()
은 date_i18n
이론적으로 날짜의 출력을 인터페이스로 완전히 가로 채서 다시 처리 할 수 있지만 함수가 이미 범위 ( false
) 타임 스탬프 입력을 벗어나면 문제가됩니다.
결론
데이터의 실제 목적과 이식성을 위해 WordPress 게시 날짜 범위 는 32 비트 Unix 타임 스탬프와 같고 1902 년에서 2037 년까지 포함 됩니다.
이 범위를 벗어난 게시 날짜 작업에 대해 감사해야합니다 (64 비트 범위의 Unix 타임 스탬프, 사실상 작동하는 MySQL 또는 대체 데이터베이스 스토리지 값). 더 넓은 범위 ( 1000 미만, 9999 이상 )의 경우 상당한 양의 사용자 지정 코드가 필요할 수 있습니다.
임의의 날짜를 구현하는 경우 다음과 같은 의미가 있습니다.
- 데이터베이스 제한이없는 형식으로 MySQL에 저장
Date/Time
Unix 타임 스탬프 제한에 영향을받지 않도록 감사 된 완전한 사용자 정의 기반 코드 및 / 또는 WordPress 함수를 사용하여 PHP에서 처리
코드 테스트 베드
다음 코드와 직접 고른 연도는 위의 연구 및 결론 테스트에 사용되었습니다.
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,
) );
}
}