PHP strtotime 함수 사용법, 구현 원리 및 소스 코드 분석_php 기술

WBOY
풀어 주다: 2016-05-16 20:24:06
원래의
1181명이 탐색했습니다.

源码位置:extdatephp_date.c

复代码 代码如下:

/* {{{ proto int strtotime(string time [, int now ])
   날짜 및 시간의 문자열 표현을 타임스탬프로 변환 */
PHP_FUNCTION(strtotime)
{
    char *times, *initial_ts;
    int   time_len, error1, error2;
    struct timelib_error_container *error;
    긴 preset_ts = 0, ts;

    timelib_time *t, *지금;
    timelib_tzinfo *tzi;

    tzi = get_timezone_info(TSRMLS_C);

    if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, “sl”, ×, &time_len, &preset_ts) != 실패) {
        /* 초기 타임스탬프가 있습니다 */
        지금 = timelib_time_ctor();

       initial_ts = emalloc(25);
        snprintf(initial_ts, 24, “@%ld UTC”,preset_ts);
        t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); /* 절대 실패해서는 안 되므로 여기서는 오류를 무시합니다. */
        timelib_update_ts(t, tzi);
        now->tz_info = tzi;
        지금->zone_type = TIMELIB_ZONETYPE_ID;
        timelib_unixtime2local(현재, t->sse);
        timelib_time_dtor(t);
        efree(initial_ts);
    } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “s|l”, ×, &time_len, &preset_ts) != 실패) {
        /* 초기 타임스탬프가 없습니다 */
        지금 = timelib_time_ctor();
        now->tz_info = tzi;
        지금->zone_type = TIMELIB_ZONETYPE_ID;
        timelib_unixtime2local(현재, (timelib_sll) 시간(NULL));
    } 그 밖의 {
        RETURN_FALSE;
    }

    if (!time_len) {
        timelib_time_dtor(현재);   
        RETURN_FALSE;
    }

    t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
    error1 = 오류->error_count;
    timelib_error_container_dtor(오류);
    timelib_fill_holes(t, 지금, TIMELIB_NO_CLONE);
    timelib_update_ts(t, tzi);
    ts = timelib_date_to_int(t, &error2);

    timelib_time_dtor(현재);
    timelib_time_dtor(t);

    if (error1 || error2) {
        RETURN_FALSE;
    } 그 밖의 {
        RETURN_LONG(ts);
    }
}
/* }}} */


strtotime函数에서 사용하는 strtotime(“-1개월”)은 한 달에 한 번씩 발행됩니다.

因此也引流写这篇文章,本文包括如下内容:

1).strtotime函数의 한 가지 용도
2).strtotime函数의 实现基本原리
3).strtotime(“-1개월”)求值失败의 원본

strtotime函数的一些사용법

1、 strtotime(“JAN”) 과 strtotime(“1월”)

这两个个个效果是一样的, city是返回指定月份的今天,如果指到份没有今天,则顺延到下一个月。代码:

复代码 代码如下:

echo date("연월일 H:i:s", strtotime("feb", strtotime("2011-03-31")));

프로그램은 2011-03-03 00:00:00을 출력합니다. 겉으로 보기에 이 결과는 반드시 우리가 원하는 결과는 아닐 수도 있지만, 이 솔루션을 결정하는 것은 무엇인가? strtotime 함수는 월을 계산할 때 월만 계산합니다. 이는 월을 지정된 월의 값으로 직접 설정하는 것과 동일하며 jan 및 January와 같이 해당 내부 값을 갖게 됩니다.

2. 첫 번째 키워드

first는 확인값을 지정할 수 있는 week, day 등의 키워드와 조합하여 사용할 수 있는 보조 키워드입니다. 예를 들어 2011년 첫 번째 일요일을 찾으려면

코드 복사 코드는 다음과 같습니다.

echo date("Y-m-d H:i:s", strtotime("두 번째 일요일", strtotime("2011-01-01"))), "
";

PHP 소스 코드에서는 first, week, day의 결합 사용이 구분되어 있습니다. 즉, first day는 처리 작업에 해당하며, 최종 C 구현에서는 day의 값이 1, 즉 d 필드로 지정됩니다. 시간 구조에서는 1로 지정됩니다. 다음 코드는
코드 복사 코드는 다음과 같습니다.

전환 (시간->relative.first_last_day_of) {
사례 1: /* 먼저 */
시간->d = 1;
         휴식;
사례 2: /* 마지막 */
시간->d = 0;
시간->m ;
         휴식;
}

3. 이전 및 다음 키워드

첫 번째와 비슷하게 이전 키워드는 week, day와 함께 사용하여 요일이나 지정된 시간 이전의 날짜를 나타낼 수 있습니다. 코드는 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

echo date("Y-m-d H:i:s", strtotime("이전 일요일", strtotime("2011-02-01"))), "
";

프로그램은 다음을 출력합니다: 2011-01-30 00:00:00
프로그램은 2011-02-01 이전의 일요일을 찾습니다.

다음 키워드는 이전 키워드와 반대되는 의미로, 다음 요일이나 모레를 나타냅니다.

4. 마지막 키워드

마지막 키워드는 이전 키워드나 마지막 키워드로 사용될 수 있습니다. 지난 일요일 날짜:

코드 복사 코드는 다음과 같습니다.

echo date("Y-m-d H:i:s", strtotime("지난 일요일", strtotime("2011-02-05"))), "
";

프로그램은 다음을 출력합니다: 2011-01-30 00:00:00

프로그램을 마지막으로 사용하는 경우, 적용 시나리오는 지정된 날짜가 있는 달의 마지막 날이 되며, 이는 date("t")의 결과와 동일합니다. 2000년 2월의 마지막 날을 찾으세요:

코드 복사 코드는 다음과 같습니다.

echo date("Y-m-d H:i:s", strtotime("마지막 날", strtotime("2000-02-01"))), "
";

첫 번째, 이전, 마지막 및 이 키워드는 re 파일에서 동일한 그룹에 속합니다.

5. 앞뒤 키워드

이 두 키워드는 하루 시간에 대한 정방향 및 역방향 작업을 수행하며 호출 형식은 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

echo date("Y-m-d H:i:s", strtotime("back of 24", strtotime("2011-02-01"))), "
";
echo date("Y-m-d H:i:s", strtotime("24의 앞부분", strtotime("2011-02-01"))), "
";

back은 지정된 시간 값 이후의 15분으로 시간을 설정하는 것을 의미합니다. 24시인 경우에는 다음날 0시 15분으로 계산됩니다.
앞은 지정된 시간 값보다 45분 전으로 시간을 설정하는 것을 의미합니다. 0시인 경우 전날의 23시 45분으로 계산됩니다.
위 코드는 2011-02-02 00:15:00 2011-02-01 23:45:00을 출력합니다. 뒤에 back of와 front of가 오는 배열은 0보다 크거나 같고 24보다 작거나 같아야 합니다.

strtotime 함수 구현의 기본 원칙
공식 문서에서는 strtotime 함수에 대해 다음과 같이 설명합니다. 이 함수는 미국 영어 날짜 형식이 포함된 문자열을 허용하고 이를 Unix 타임스탬프로 구문 분석하려고 시도합니다(1970년 1월 1일 00:00:00 GMT 숫자 이후의 초). , 해당 값은 now 매개변수에 지정된 시간을 기준으로 합니다. 이 매개변수가 제공되지 않으면 현재 시스템 시간이 사용됩니다.

PHP4부터 존재했던 표준 PHP 내장 함수입니다. strtotime 함수는 확장으로 로드되며 전체 구현은 ext/date 디렉터리에서 사용할 수 있습니다. 표준 내장 함수로서 정의 형식도 다음과 같이 표준입니다.

코드 복사 코드는 다음과 같습니다.

PHP_FUNCTION(strtotime)
// 두 번째 매개변수 유무에 관계없이 입력 처리

// 관련 함수를 호출하여 문자열 파싱 및 결과 계산 구현

// 결과 반환
}


입력 처리에서는 두 매개변수가 모두 존재하는 상황을 먼저 식별하여 처리하며, 이 상태가 아니면 두 번째 매개변수가 없는 상황을 처리하여 오류를 보고하고 FALSE를 반환한다. .

strtotime 함수의 첫 번째 매개변수는 문자열입니다. 이 문자열의 경우 복잡성으로 인해 PHP는 어휘 구문 분석과 동일한 도구인 re2c를 사용합니다. /ext/date/lib 디렉토리에서 pars_date.re 파일의 원본 re 파일을 볼 수 있습니다. 사용자가 매개변수 형태로 문자열을 전달하면 해당 문자열은 처리를 위해 이 프로그램으로 전달되며, 다른 문자열에 따라 다른 처리 기능이 일치됩니다. 예를 들어 strtotime("yesterday")이 호출되면 문자열을 분석할 때 어제 문자열과 일치합니다. 이 문자열에 해당하는 함수는 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

'어제'
{
DEBUG_OUTPUT("어제");
TIMELIB_INIT;
TIMELIB_HAVE_RELATIVE();
TIMELIB_UNHAVE_TIME();

s->time->relative.d = -1;
TIMELIB_DEINIT;
TIMELIB_RELATIVE를 반환합니다.
}


다음은 몇 가지 주요 구조입니다.
코드 복사 코드는 다음과 같습니다.

typedef 구조체 스캐너 {
    int           fd;
    uchar        *lim, *str, *ptr, *cur, *tok, *pos;
    부호 없는 int 행, len;
    struct timelib_error_container *errors;

    struct timelib_time *time;
    const timelib_tzdb  *tzdb;
} 스캐너;

typedef struct timelib_time {
    timelib_sll      y, m, d;     /* 연, 월, 일 */
    timelib_sll      h, i, s;     /* 시, 분, 초 */
    더블           f;           /* 분수 */
    int              z;           /* GMT 오프셋(분) */
    문자            *tz_abbr;     /* 시간대 약어(표시 전용) */
    timelib_tzinfo  *tz_info;     /* 시간대 구조 */
    서명된 int       dst;         /* DST 구역을 구문 분석하는 경우 플래그 지정 */
    timelib_rel_time 상대;

    timelib_sll      sse;         /* 에포크 이후 초 */

    unsigned int   have_time, have_date, have_zone, have_relative, have_weeknr_day;

    unsigned int   sse_uptodate; /* !0 sse 멤버가 날짜/시간 멤버와 최신 상태인 경우 */
    서명되지 않은 int   tim_uptodate; /* !0 날짜/시간 멤버가 sse 멤버와 최신 상태인 경우 */
    unsigned int   is_localtime; /*  현재 구조체가 현지 시간을 나타내는 경우 1, GMT인 경우 0 */
    unsigned int   zone_type;    /*  1시간 오프셋,
                                  *  3 시간대 식별자,
                                  *  2 TimeZone 약어 */
} timelib_time;

typedef struct timelib_rel_time {
    timelib_sll y, m, d; /* 연, 월, 일 */
    timelib_sll h, i, s; /* 시, 분, 초 */

    int 평일; /* '다음 월요일'로 날짜를 저장합니다 */
    int weekday_behavior; /* 0: 현재 날짜는 앞으로 나아갈 때 계산되지 *않습니다*; 1: 현재 날짜를 *계산해야* 합니다 */

    int first_last_day_of;
    int 반전; /* 차이를 반전할지 여부 */
    timelib_sll 일; /* Y-M-D 차이 대신 *일* 수를 포함합니다 */

    timelib_special  스페셜;
    unsigned int   have_weekday_relative, have_special_relative;
} timelib_rel_time;


s->time->relative.d = -1;所表示的의식 思是当前时间的是对天数是-1.这些中间结果计算는 판매됩니다.

strtotime(“-1개월”)求值失败의 원본

PHP样实现也无可厚不.只是我们的需求决决了我们不能使用这种方法,因此我们称其为求值失败。


复代码 代码如下:

reltextunit = (('초'|'초'|'분'|'분'|'시'|'일'|'보름'|'포스트나잇'|'월'|'년') 's'?) | '주' | daytext;

relnumber = ([ -]*[ t]*[0-9] );
상대 = relnumber 공간? (reltextunit | 'week' );


결국 상대는 일련의 작업에 해당합니다. 프로그램은 앞에 있는 -1을 인식하고 뒤에 있는 월 문자열은 작업 유형인 TIMELIB_MONTH에 해당합니다. 이후 다음 코드와 같이 식별된 번호와 작업 유형을 기반으로 작업을 수행합니다.
코드 복사 코드는 다음과 같습니다.

사례 TIMELIB_MONTH: s->time->relative.m = 금액 * relunit->multiplier break;

위 코드는 월에서 1을 뺀 상대값을 직접 기록합니다. 그러나 2월에 31일이 없는 3월 31일과 같은 상황에서는 프로그램이 자동으로 다음 달의 날짜를 계산합니다.
관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿