2012-10-31 3 views
2

작업은 무엇입니까?
프로젝트 표준에 따라 특정 표준 시간대 오프셋에 대한 DST 규칙을 계산해야합니다. date_default_timezone_set()과 같은 표준 도구를 통해을 적용 할 수 없습니다. 소프트웨어 구성에 의존 할 수 없으며 일부 DST 규칙이 변경되는 경우 업데이트 할 수 없기 때문입니다.사용자 지정 가능한 DST 규칙

나는 무엇을 가지고 있습니까?
DST 전환 날짜가 지난주의 일이고 지난주의 전환 일이 다음 달이면 나는 지난 주 수를 감소시켜야합니다.

$week = 5; 
if (
    (1 + 7 * ($week - 1)) 
    + $start['day_of_week'] 
    - date('w', mktime(0, 0, 0, $start['month'], 1, date('Y', $start['timestamp']))) 
    > 
    date('t', $start['month'])) 
{ 
    $week--; 
} 

내가 찾던 : 지금 나는 오직 하나의 추한 해결책을 가지고 있습니다?
이 간단한 솔루션 또는 링크를 찾고 싶습니다.

+2

흥미로운 질문입니다. 그리고 최근의 모든 혼란과 함께 러시아 엔지니어로부터 오는 것이 놀랄 일이 아닙니다 :) 기본 제공 표준 시간대 목록/오프셋 목록을 사용자 정의 할 수 있습니까? 날짜 함수가 사용하는 함수? 나는 그들이 어떤 형식으로 저장되어 있는지, 그리고 PHP를 다시 컴파일하지 않고 액세스 할 수 있는지 여부는 모르지만 –

+0

을보고 싶을 수도 있습니다. AFAIK 그것은 시스템/라이브러리에 의존하며 PHP를 통해 액세스 할 수 없습니다. 그러나 나는 그것을 볼 것입니다. =) – Skpd

+0

예, 시스템을 꽤 심층적으로 구축 한 것 같습니다. [DateTime의 전환을 읽을 수 있습니다.] (http://www.php.net/manual/en/datetimezone.gettransitions.php) 쓰기가 없습니다. –

답변

1

시스템 전체의 표준 시간대 데이터베이스를 사용하고 사용자 정의 업데이트를 유지 관리 할 수 ​​있습니다.

Official TZ database repository at IANA

그것은 당신이 그 시간 함수를 사용하는 모든 프로그램에서 결과적으로 필요할 때 수정하고 glibc 시간 함수에서 사용할 수있는 바이너리 파일로 다시 컴파일 할 수 있습니다 소스 파일로 사용할 수 있습니다. 배포판에서 이러한 업데이트를 수행하거나 사용자 정의 변경 사항을 잃게되는 경우 해당 데이터베이스에 대한 자동 업데이트를 비활성화하는 방법을 찾아야 할 수도 있습니다.

PHP가 실제로 시스템 전체 TZ 데이터베이스를 따르는지는 확실하지 않습니다. PECL timezonedb 패키지가 IANA 데이터베이스의 별도로 다시 컴파일 된 버전임을 나타내므로 이 아니므로은 시스템 전체 데이터베이스에서 변경 사항을 관찰 할 수 있습니다.

putenv('TZ=America/New_York'); 
$offset = exec('date +%z'); 
: PHP는 시스템 전체 데이터베이스의 변화를 무시하면

, 당신은 예를 들어 glibc 시간대를 인식하는 시간 함수를 사용하고 그 시간대 오프셋, 리턴 지원하는 외부 프로그램을 호출하여 오프셋 영역을 검색 할 수 있습니다

$offset±HHMM 형식이므로 추가 구문 분석이 필요합니다.

또한이 현재 시간과 다른 특정 타임 스탬프, 오프셋 보정 찾을 수 있습니다 : 타임 스탬프는 신뢰할 수없는 소스에서 오는 경우

물론
$unix_timestamp = 1350757594; 
$offset = exec('date +%z [email protected]'.$unix_timestamp); 

escapeshellarg을 통해 적절한 필터링이 요구 될 것이다.

업데이트 : 다음은 단일 DST 규칙 집합의 솔루션입니다. 외부 자원 예제 코드는 표준 유럽 DST 규칙 및 동부 유럽 시간 오프셋을 사용

function calculate_offset($ts) { 
    static $standard_offset = 2; // = +2:00 
    static $dst_offset  = 3; // = +3:00 
    static $dst_start  = 'last Sunday of March %d 1:00'; 
    static $dst_end   = 'last Sunday of October %d 1:00'; 

    date_default_timezone_set('UTC'); 

    $y = idate('Y', $ts); 
    $start = strtotime(sprintf($dst_start, $y)); 
    $end = strtotime(sprintf($dst_end, $y)); 

    if ($start < $end) { 
     // Northern hemisphere, DST starts earlier in the year than it ends 
     $offset = ($ts >= $start && $ts < $end)? $dst_offset: $standard_offset; 
    } else { 
     // Southern hemisphere, DST ends earlier in the year than it starts 
     $offset = ($ts >= $end && $ts < $start)? $standard_offset: $dst_offset; 
    } 
    $utc_time = strftime('%Y/%m/%d %H:%M:%S', $ts); 
    $local_time = strftime('%Y/%m/%d %H:%M:%S', $ts + $offset * 60 * 60); 
    printf("TS: %d; Offset: +%02d:00; UTC: %s; Local: %s\n", $ts, $offset, $utc_time, $local_time); 
} 

사용되지 않습니다. strtotime : Relative Formats에 의해 이해되는 형식으로 DST 시작 및 종료 규칙을 표현하는 방법을 찾아야합니다.DST 시작/종료 규칙의 %d은 타임 스탬프가 속하는 연도로 바뀌므로 평일 주중 규칙은 특정 연도의 정확한 날짜를 찾습니다. 모든 계산은 UTC 시간으로 수행되므로 규칙은 DTC 시작/종료 시간 (UTC)을 참조해야합니다.

+0

고마워, 내가 너에게 알려주지. – Skpd

+0

좋은 해결책이지만, ** ** 시스템 변경없이 작동 할 수있는 무언가를 찾고 있습니다. 우리가 ssh 액세스없이 외부 공간에 서버를 가지고 있지만 원격 DB가 있다고 가정하십시오.) – Skpd

+0

감사합니다. – Skpd

관련 문제