簡體   English   中英

filemtime 可以在夏令時與 strtotime 進行比較嗎?

[英]Can filemtime be compared with strtotime at the daylight savings change?

如果源數據文件過期,我有一些 PHP 代碼可以發送警告並自動關閉服務。 這是使用以下比較完成的:

警告: filemtime($file_location) < strtotime('-15 minute')

考慮服務停機: filemtime($file_location) < strtotime('-1 hour')

對於夏令時開始時 CDT 凌晨 3:00 開始的 1 小時,這會錯誤地將文件報告為超過 15 分鍾。 快要結束時,它還會錯誤地將文件報告為超過 1 小時。 CDT 凌晨 4:00 一切恢復正常。

有什么我不知道的關於 filemtime() 或 strtotime() 函數可以解釋這種行為嗎? 我的理解是兩者都返回 UNIX 時間戳,並且時間戳是按照 UTC 定義的,所以我不確定是什么導致了這個問題。

根據到目前為止的答案,我在我們的服務器上運行了這個測試:

`

for($i = 1; $i <=4; $i++){
    // let's say current time is this:
    date_default_timezone_set('America/Winnipeg');
    $current_timestamp = strtotime('2016-03-13 0'.$i.':00:00'); // 1457856060

    // DST start at 03:00 that day, so 60 minutes before the time should be 01:01
    $ts = $current_timestamp - 1*60*60;
    echo '-3600s:   ', $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
    // 1457852460, 2016-10-30 02:59:00, correct

    // now let's test strtotime with -1 hour
    $ts = strtotime('-1 hour', $current_timestamp);
    echo '-1 hour:  ', $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
    // 1457856060, 2016-10-30 03:01:00, completely wrong

    // DateTime implementation seems smarter:
    $dt = new DateTime();
    $dt->setTimestamp($current_timestamp);
    $dt->sub(new DateInterval('PT1H'));
    echo 'sub PT1H: ', $dt->getTimestamp(), ", ", $dt->format('Y-m-d H:i:s'), "\n";
    // 1457856060, 2016-10-30 03:01:00, correct

    echo "\n\n";
    echo 'TS        ', $current_timestamp, ", ", date('Y-m-d H:i:s', $current_timestamp), "\n";
    echo "\n\n";
}

`

-3600s: 1457848800, 2016-03-13 00:00:00

-1 小時:1457848800,2016-03-13 00:00:00

子 PT1H: 1457848800, 2016-03-13 00:00:00

TS 1457852400, 2016-03-13 01:00:00

-3600s: 1457852400, 2016-03-13 01:00:00

-1 小時:1457856000,2016-03-13 03:00:00

子 PT1H: 1457856000, 2016-03-13 03:00:00

TS 1457856000, 2016-03-13 03:00:00

-3600s: 1457852400, 2016-03-13 01:00:00

-1 小時:1457856000,2016-03-13 03:00:00

子 PT1H: 1457856000, 2016-03-13 03:00:00

TS 1457856000, 2016-03-13 03:00:00

-3600s: 1457856000, 2016-03-13 03:00:00

-1 小時:1457856000,2016-03-13 03:00:00

子 PT1H: 1457856000, 2016-03-13 03:00:00

TS 1457859600, 2016-03-13 04:00:00

這令人深感困惑。 在我的時區,夏令時從 3 月 27 日開始,以下所有表達式都返回相同的 UNIX 時間戳:

var_dump(strtotime("27 March 2016 02:00"));
var_dump(strtotime("- 60 minute", strtotime("27 March 2016 02:00")));
var_dump(strtotime("- 1 hour", strtotime("27 March 2016 02:00")));
var_dump(strtotime("27 March 2016 02:00 - 1 hour"));
var_dump((new DateTime("27 March 2016 02:00"))->format("U"));
var_dump((new DateTime("27 March 2016 02:00"))->sub(new DateInterval("PT1H"))->format("U"));

如果我對此足夠認真,我也許可以相信這是預期的行為。 3 月 27 日 01:00此處不存在 但這肯定不是直觀的。

更讓人困惑的是,從02:00減去15分鍾就得到了未來的答案,即02:45。 即使第一個結果在你眯得足夠遠的情況下有點意義,但這個結果肯定是一個錯誤。

一個關於此的公開錯誤報告,該報告已近 4 年未受影響。

這給您留下了兩個選擇。 您可以在代碼中添加一個if子句,如果初始減法沒有減少時間戳,則減去 2 小時或 75 分鍾。 或者您可以簡單地從當前時間戳中減去 3600 或 900 秒,而不是使用strtotime 兩者都不是特別優雅,但我們就是這樣。

似乎strtotime不夠聰明,無法在對相對值進行操作時考慮 DST 更改:

// let's say current time is this:
date_default_timezone_set('Europe/Berlin');
$current_timestamp = strtotime('2016-10-30 01:59:00'); // 1477785540

// DST ends at 03:00 that day, so 120 minutes later the time should be 02:59
$ts = $current_timestamp + 2*60*60;
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477792740, 2016-10-30 02:59:00, correct

// now let's test strtotime with +2 hours
$ts = strtotime('+2 hours', $current_timestamp);
echo $ts, ", ", date('Y-m-d H:i:s', $ts), "\n";
// 1477796340, 2016-10-30 03:59:00, completely wrong

// DateTime implementation seems smarter:
$dt = new DateTime();
$dt->setTimestamp($current_timestamp);
$dt->add(new DateInterval('PT2H'));
echo $dt->getTimestamp(), ", ", $dt->format('Y-m-d H:i:s');
// 1477792740, 2016-10-30 02:59:00, correct

在您的特定情況下,我只是直接比較時間戳(顯然,差異將以秒為單位),但將DateTimeTimeInterval一起使用也是一種選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM